zoukankan      html  css  js  c++  java
  • Promise做异步实例

    Promise做异步实例

    一、总结

    一句话总结:

    new Promise实例,then方法执行回调,catch抛出异常
    function getFileByPath(fpath) {
      return new Promise(function (resolve, reject) {
        fs.readFile(fpath, 'utf-8', (err, dataStr) => {
    
          if (err) return reject(err)
          resolve(dataStr)
    
        })
      })
    }
    
    // 有时候,我们有这样的需求,个上面的需求刚好相反:如果 后续的Promise 执行,依赖于 前面 Promise 执行的结果,如果前面的失败了,则后面的就没有继续执行下去的意义了,此时,我们想要实现,一旦有报错,则立即终止所有 Promise的执行;
    
    getFileByPath('./files/1.txt')
      .then(function (data) {
        console.log(data)
    
        // 读取文件2
        return getFileByPath('./files/22.txt')
      })
      .then(function (data) {
        console.log(data)
    
        return getFileByPath('./files/3.txt')
      })
      .then(function (data) {
        console.log(data)
      })
      .catch(function (err) { // catch 的作用: 如果前面有任何的 Promise 执行失败,则立即终止所有 promise 的执行,并 马上进入 catch 去处理 Promise中 抛出的异常;
        console.log('这是自己的处理方式:' + err.message)
      })

    1、回调函数解决异步实例?

    通过回调函数接收异步操作的结果,不然正常情况下没有办法接收到异步操作的结果
    function getFileByPath(fpath, callback) {
      fs.readFile(fpath, 'utf-8', (err, dataStr) => {
        // 如果报错了,进入if分支后,if后面的代码就没有必要执行了
        if (err) return callback(err)
        // console.log(dataStr)
        // return dataStr
        callback(null, dataStr)
      })
    }
    
    /* var result = getFileByPath(path.join(__dirname, './files/1.txt'))
    console.log(result) */
    getFileByPath(path.join(__dirname, './files/11.txt'), (err, dataStr) => {
      // console.log(dataStr + '-----')
      if (err) return console.log(err.message)
      console.log(dataStr)
    })

    2、为什么回调函数解决异步问题会有回调地狱的问题?

    回调地狱是因为要保证异步函数的顺序,比如异步函数先读取文件1,读取文件1成功之后(回调内),又异步函数读取文件2,以此类推,等等

    3、Promise函数作用?

    Promise解决 回调函数解决异步问题造成的回调地狱问题

    4、Promise注意点?

    Promise本身是一个构造函数

    5、每当 new 一个 Promise 实例的时候,就会立即 执行这个 异步操作中的代码?

    new Promise 的时候,除了能够得到 一个 promise 实例之外,还会立即调用 我们为 Promise 构造函数传递的那个 function,执行这个 function 中的 异步操作代码
    // 也就是说,new 的时候,除了能够得到 一个 promise 实例之外,还会立即调用 我们为 Promise 构造函数传递的那个 function,执行这个 function 中的 异步操作代码;
    var promise = new Promise(function () {
      fs.readFile('./files/2.txt', 'utf-8', (err, dataStr) => {
        if (err) throw err
        console.log(dataStr)
      })
    })

    6、Promise对象中的resolve和reject怎么来的?

    resolve和reject是回调函数,通过then传进去的回调函数,then还是比回调中的异步操作执行的快

    7、Promise执行步骤?

    先返回promise对象,然后执行then,然后通过then传递resolve和reject,然后执行完异步操作,然后执行resolve或者reject
    function getFileByPath(fpath) {
      return new Promise(function (resolve, reject) {
        fs.readFile(fpath, 'utf-8', (err, dataStr) => {
    
          if (err) return reject(err)
          resolve(dataStr)
    
        })
      })
    }
    
    getFileByPath('./files/2.txt')
      .then(function (data) {
        console.log(data + '-------')
      }, function (err) {
        console.log(err.message)
      })

    8、如果前面的 Promise 执行失败了,但是,不要影响后续 promise 的正常执行,我们应该怎么做?

    我们可以单独为 每个 promise,通过 .then 指定一下失败的回调;

    9、promise中catch的作用是什么?

    如果前面有任何的 Promise 执行失败,则立即终止所有 promise 的执行,并 马上进入 catch 去处理 Promise中 抛出的异常
    function getFileByPath(fpath) {
      return new Promise(function (resolve, reject) {
        fs.readFile(fpath, 'utf-8', (err, dataStr) => {
    
          if (err) return reject(err)
          resolve(dataStr)
    
        })
      })
    }
    
    // 有时候,我们有这样的需求,个上面的需求刚好相反:如果 后续的Promise 执行,依赖于 前面 Promise 执行的结果,如果前面的失败了,则后面的就没有继续执行下去的意义了,此时,我们想要实现,一旦有报错,则立即终止所有 Promise的执行;
    
    getFileByPath('./files/1.txt')
      .then(function (data) {
        console.log(data)
    
        // 读取文件2
        return getFileByPath('./files/22.txt')
      })
      .then(function (data) {
        console.log(data)
    
        return getFileByPath('./files/3.txt')
      })
      .then(function (data) {
        console.log(data)
      })
      .catch(function (err) { // catch 的作用: 如果前面有任何的 Promise 执行失败,则立即终止所有 promise 的执行,并 马上进入 catch 去处理 Promise中 抛出的异常;
        console.log('这是自己的处理方式:' + err.message)
      })

    二、Promise做异步实例

    博客对应课程的视频位置:

    1、封装读取文件的方法

     1 // 需求:你要封装一个方法,我给你一个要读取文件的路径,你这个方法能帮我读取文件,并把内容返回给我
     2 
     3 const fs = require('fs')
     4 const path = require('path')
     5 
     6 // 这是普通读取文件的方式
     7 /* fs.readFile(path.join(__dirname, './files/1.txt'), 'utf-8', (err, dataStr) => {
     8   if (err) throw err
     9   console.log(dataStr)
    10 }) */
    11 
    12 // 初衷: 给定文件路径,返回读取到的内容
    13 // 我们可以规定一下, callback 中,有两个参数,第一个参数,是 失败的结果;第二个参数是成功的结果;
    14 // 同时,我们规定了: 如果成功后,返回的结果,应该位于 callback 参数的第二个位置,此时, 第一个位置 由于没有出错,所以,放一个 null;  如果失败了,则 第一个位置放 Error对象,第二个位置防止一个 undefined
    15 function getFileByPath(fpath, callback) {
    16   fs.readFile(fpath, 'utf-8', (err, dataStr) => {
    17     // 如果报错了,进入if分支后,if后面的代码就没有必要执行了
    18     if (err) return callback(err)
    19     // console.log(dataStr)
    20     // return dataStr
    21     callback(null, dataStr)
    22   })
    23 }
    24 
    25 /* var result = getFileByPath(path.join(__dirname, './files/1.txt'))
    26 console.log(result) */
    27 getFileByPath(path.join(__dirname, './files/11.txt'), (err, dataStr) => {
    28   // console.log(dataStr + '-----')
    29   if (err) return console.log(err.message)
    30   console.log(dataStr)
    31 })

    2、封装读取文件的方法-提高版

     1 // 需求:你要封装一个方法,我给你一个要读取文件的路径,你这个方法能帮我读取文件,并把内容返回给我
     2 
     3 const fs = require('fs')
     4 const path = require('path')
     5 
     6 
     7 function getFileByPath(fpath, succCb, errCb) {
     8   fs.readFile(fpath, 'utf-8', (err, dataStr) => {
     9     if (err) return errCb(err)
    10     succCb(dataStr)
    11   })
    12 }
    13 
    14 // getFileByPath(path.join(__dirname, './files/11.txt'), function (data) {
    15 //   console.log(data + '娃哈哈,成功了!!!')
    16 // }, function (err) {
    17 //   console.log('失败的结果,我们使用失败的回调处理了一下:' + err.message)
    18 // })
    19 
    20 // 需求: 先读取文件1,再读取文件2,最后再读取文件3
    21 // 回调地狱
    22 // 使用 ES6 中的 Promise,来解决 回调地狱的问题;
    23 // 问: Promise 的本质是要干什么的:就是单纯的为了解决回调地狱问题;并不能帮我们减少代码量;
    24 getFileByPath(path.join(__dirname, './files/1.txt'), function (data) {
    25   console.log(data)
    26 
    27   getFileByPath(path.join(__dirname, './files/2.txt'), function (data) {
    28     console.log(data)
    29 
    30     getFileByPath(path.join(__dirname, './files/3.txt'), function (data) {
    31       console.log(data)
    32     })
    33   })
    34 })

    3、Promise概念介绍

     1 // 1. Promise 是一个 构造函数,既然是构造函数, 那么,我们就可以  new Promise() 得到一个 Promise 的实例;
     2 // 2. 在 Promise 上,有两个函数,分别叫做 resolve(成功之后的回调函数) 和 reject(失败之后的回调函数)
     3 // 3. 在 Promise 构造函数的 Prototype 属性上,有一个 .then() 方法,也就说,只要是 Promise 构造函数创建的实例,都可以访问到 .then() 方法
     4 // 4. Promise 表示一个 异步操作;每当我们 new 一个 Promise 的实例,这个实例,就表示一个具体的异步操作;
     5 // 5. 既然 Promise 创建的实例,是一个异步操作,那么,这个 异步操作的结果,只能有两种状态:
     6 //  5.1 状态1: 异步执行成功了,需要在内部调用 成功的回调函数 resolve 把结果返回给调用者;
     7 //  5.2 状态2: 异步执行失败了,需要在内部调用 失败的回调函数 reject 把结果返回给调用者;
     8 //  5.3 由于 Promise 的实例,是一个异步操作,所以,内部拿到 操作的结果后,无法使用 return 把操作的结果返回给调用者; 这时候,只能使用回调函数的形式,来把 成功 或 失败的结果,返回给调用者;
     9 // 6. 我们可以在 new 出来的 Promise 实例上,调用 .then() 方法,【预先】 为 这个 Promise 异步操作,指定 成功(resolve) 和 失败(reject) 回调函数;
    10 
    11 
    12 // 注意:这里 new 出来的 promise, 只是代表 【形式上】的一个异步操作;
    13 // 什么是形式上的异步操作:就是说,我们只知道它是一个异步操作,但是做什么具体的异步事情,目前还不清楚
    14 // var promise = new Promise()
    15 
    16 
    17 // 这是一个具体的异步操作,其中,使用 function 指定一个具体的异步操作
    18 /* var promise = new Promise(function(){
    19   // 这个 function 内部写的就是具体的异步操作!!!
    20 }) */
    21 
    22 const fs = require('fs')
    23 
    24 // 每当 new 一个 Promise 实例的时候,就会立即 执行这个 异步操作中的代码
    25 // 也就是说,new 的时候,除了能够得到 一个 promise 实例之外,还会立即调用 我们为 Promise 构造函数传递的那个 function,执行这个 function 中的 异步操作代码;
    26 /* var promise = new Promise(function () {
    27   fs.readFile('./files/2.txt', 'utf-8', (err, dataStr) => {
    28     if (err) throw err
    29     console.log(dataStr)
    30   })
    31 }) */
    32 
    33 
    34 // 初衷: 给路径,返回读取到的内容
    35 function getFileByPath(fpath) {
    36   return new Promise(function (resolve, reject) {
    37     fs.readFile(fpath, 'utf-8', (err, dataStr) => {
    38 
    39       if (err) return reject(err)
    40       resolve(dataStr)
    41 
    42     })
    43   })
    44 }
    45 
    46 /* getFileByPath('./files/2.txt')
    47   .then(function (data) {
    48     console.log(data + '-------')
    49   }, function (err) {
    50     console.log(err.message)
    51   }) */

    4、使用Promise解决回调地狱

     1 const fs = require('fs')
     2 
     3 function getFileByPath(fpath) {
     4   return new Promise(function (resolve, reject) {
     5     fs.readFile(fpath, 'utf-8', (err, dataStr) => {
     6 
     7       if (err) return reject(err)
     8       resolve(dataStr)
     9 
    10     })
    11   })
    12 }
    13 
    14 // 先读取文件1,在读取2,最后读取3
    15 // 注意: 通过 .then 指定 回调函数的时候,成功的 回调函数,必须传,但是,失败的回调,可以省略不传
    16 // 这是一个 错误的示范,千万不要这么用; 硬是把 法拉利,开成了 拖拉机;
    17 /* getFileByPath('./files/1.txt')
    18   .then(function (data) {
    19     console.log(data)
    20 
    21     getFileByPath('./files/2.txt')
    22       .then(function (data) {
    23         console.log(data)
    24 
    25         getFileByPath('./files/3.txt')
    26           .then(function (data) {
    27             console.log(data)
    28           })
    29       })
    30   }) */
    31 
    32 // 读取文件1
    33 // 在上一个 .then 中,返回一个新的 promise 实例,可以继续用下一个 .then 来处理
    34 
    35 
    36 // 如果 ,前面的 Promise 执行失败,我们不想让后续的Promise 操作被终止,可以为 每个 promise 指定 失败的回调
    37 /* getFileByPath('./files/11.txt')
    38   .then(function (data) {
    39     console.log(data)
    40 
    41     // 读取文件2
    42     return getFileByPath('./files/2.txt')
    43   }, function (err) {
    44     console.log('这是失败的结果:' + err.message)
    45     // return 一个 新的 Promise
    46     return getFileByPath('./files/2.txt')
    47   })
    48   .then(function (data) {
    49     console.log(data)
    50 
    51     return getFileByPath('./files/3.txt')
    52   })
    53   .then(function (data) {
    54     console.log(data)
    55   }).then(function (data) {
    56     console.log(data)
    57   }) */
    58 
    59 // console.log('OKOKOK')
    60 
    61 
    62 
    63 // 当 我们有这样的需求: 哪怕前面的 Promise 执行失败了,但是,不要影响后续 promise 的正常执行,此时,我们可以单独为 每个 promise,通过 .then 指定一下失败的回调;
    64 
    65 // 有时候,我们有这样的需求,个上面的需求刚好相反:如果 后续的Promise 执行,依赖于 前面 Promise 执行的结果,如果前面的失败了,则后面的就没有继续执行下去的意义了,此时,我们想要实现,一旦有报错,则立即终止所有 Promise的执行;
    66 
    67 getFileByPath('./files/1.txt')
    68   .then(function (data) {
    69     console.log(data)
    70 
    71     // 读取文件2
    72     return getFileByPath('./files/22.txt')
    73   })
    74   .then(function (data) {
    75     console.log(data)
    76 
    77     return getFileByPath('./files/3.txt')
    78   })
    79   .then(function (data) {
    80     console.log(data)
    81   })
    82   .catch(function (err) { // catch 的作用: 如果前面有任何的 Promise 执行失败,则立即终止所有 promise 的执行,并 马上进入 catch 去处理 Promise中 抛出的异常;
    83     console.log('这是自己的处理方式:' + err.message)
    84   })
     
  • 相关阅读:
    《Python机器学习及实践:从零开始通往Kaggle竞赛之路》
    CPA专业阶段单科成绩有5年有效期限,即从通过科目考试的第一年算起
    升级gitk后,Error in startup script: unknown color name "lime"
    新三板:精选反馈问题103题(建议收藏)
    jQuery .on
    onload in JavaScript
    The JavaScript this Keyword
    JavaScript method overload
    JavaScript modularity with RequireJS (from spaghetti code to ravioli code)
    Understanding RequireJS for Effective JavaScript Module Loading
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/12776433.html
Copyright © 2011-2022 走看看