Promise的自我理解

145 阅读2分钟

Promise的自我理解

1、回调地狱

多层回调函数的相互嵌套,就形成了回调地狱。

  • 回调地狱的缺点:

    1、代码耦合性太强,牵一发而动全身,难以维护 2、大量冗余的代码相互嵌套,代码的可读性变差

  • 为解决回调地狱问题,ES6新增了Promise概念

2、Promise的基本概念

  1. 它是一个构造函数,可以new一个实例化对象出来, new Promise(),代表一个异步操作

  2. Promise.prototype 上包含一个 .then() 方法, new Promise()得到一个实例化对象,可以通过原型链的方式访问到 .then() 方法

  3. .then() 方法用来预先指定成功和失败的回调函数

    • p.then(成功的回调函数,失败的回调函数)
    • p.then(result => { }, error => { })
    • 调用 .then() 方法时,成功的回调函数是必选的、失败的回调函数是可选的
    • 如果上一个 .then() 方法中返回了一个新的 Promise 实例对象,则可以通过下一个 .then() 继续进行处理。通过 .then() 方法的链式调用,就解决了回调地狱的问题。

3、基于 Promise 按顺序读取文件的内容

Promise 支持链式调用,从而来解决回调地狱的问题。链式操作中如果发生了错误,可以使用 Promise.prototype.catch 方法进行捕获和处理,例代码如下:

import thenFs from 'then-fs'
​
thenFs
  .readFile('./files/1.txt', 'utf8')//返回一个Promise实例对象
  .catch((err) => {
    console.log(err.message)//利用catch方法捕获处理异常,并不会影响后续代码执行
  })
  .then((r1) => {  //通过then方法为第一个实例化对象指定成功后的回调函数
    console.log(r1)
    return thenFs.readFile('./files/2.txt', 'utf8')//在第一个then方法中返回一个新的Promise对象
  })
  .then((r2) => {
    console.log(r2)
    return thenFs.readFile('./files/3.txt', 'utf8')//在第二个then方法中返回一个新的Promise对象
  })
  .then((r3) => {
    console.log(r3)
  }

4、Promise all() 和Promise.race() 方法

Promise.all() 方法会发起并行的 Promise 异步操作,等所有的异步操作全部结束后才会执行下一步的 .then 操作(等待机制)。

Promise.race() 方法会发起并行的 Promise 异步操作,只要任何一个异步操作完成,就立即执行下一步的 .then 操作(赛跑机制)。

示例代码如下:

import thenFs from 'then-fs'const promiseArr = [
  thenFs.readFile('./files/3.txt', 'utf8'),
  thenFs.readFile('./files/2.txt', 'utf8'),
  thenFs.readFile('./files/1.txt', 'utf8'),
]
Promise.all(promiseArr).then(result => {
  console.log(result) //按顺序输出结构 321
})
Promise.race(promiseArr).then(result => {
  console.log(result) //结果顺序不定
})

5、基于 Promise 封装读文件的方法

如果想要创建具体的异步操作,则需要在 new Promise() 构造函数期间,传递一个 function 函数,将具体的异步操作定义到 function 函数内部。

通过 .then() 指定的成功和失败的回调函数,可以在 function 的形参中进行接收,Promise 异步操作的结果,可以调用 resolve 或 reject 回调函数进行处理。

import fs from 'fs'function getFile(fpath) {
  return new Promise(function (resolve, reject) {
    fs.readFile(fpath, 'utf8', (err, dataStr) => {
      if (err) return reject(err)
      resolve(dataStr)
    })
  })
}
​
getFile('./files/11.txt')
  .then((r1) => {
    console.log(r1)
  })
  .catch((err) => console.log(err.message))

\