Promise的自我理解
1、回调地狱
多层回调函数的相互嵌套,就形成了回调地狱。
-
回调地狱的缺点:
1、代码耦合性太强,牵一发而动全身,难以维护 2、大量冗余的代码相互嵌套,代码的可读性变差
-
为解决回调地狱问题,ES6新增了Promise概念
2、Promise的基本概念
-
它是一个构造函数,可以new一个实例化对象出来, new Promise(),代表一个异步操作
-
Promise.prototype 上包含一个 .then() 方法, new Promise()得到一个实例化对象,可以通过原型链的方式访问到 .then() 方法
-
.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))
\