「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」。
建议阅读前两篇文章
从零手撕Promise,掌握Promise的实现原理。(1)
从零手撕Promise,掌握Promise的实现原理。(2)
回顾
通过上一篇文章的介绍,我们已经完成了基础版本的promise,如下
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class Promise{
constructor(executor){
this.state = PENDING
this.value = undefined
this.reason = undefined
//存放onFulfilled
this.onResolvedCallbacks = []
//存放onRejected
this.onRejectedCallbacks = []
const resolve = (value) => {
if (this.state === PENDING) {
this.value = value
this.state = FULFILLED
//promise实例状态改变后调用暂存的onFulfilled
this.onResolvedCallbacks.forEach(fn => fn())
}
}
const reject = (reason) => {
if (this.state === PENDING) {
this.reason = reason
this.state = REJECTED
//promise实例状态改变后调用的onRejected
this.onRejectedCallbacks.forEach(fn => fn())
}
}
try {
//executor函数执行过程中出错,将会导致Promise失败
executor(resolve,reject)
} catch (error) {
reject(error)
}
}
then(onFulfilled, onRejected){
if (this.state === FULFILLED) {
onFulfilled(this.value)
}
if (this.state === REJECTED) {
onRejected(this.reason)
}
if (this.state === PENDING) {
//如果此时promise实例的状态还未确定,我们需要将onFulfilled与onRejected存起来,等到promise实例状态改变后再去调用
this.onResolvedCallbacks.push(() => {
onFulfilled(this.value)
})
this.onRejectedCallbacks.push(() => {
onRejected(this.reason)
})
}
}
}
回调地狱
在实现Promise的then链调用机制之前我们要先来了解一下回调地狱,以及用Promise如何去解决回调地狱.
- 有两个文本文件
age.txt和name.txt,内容分别如下。
- 我需要读取到
age.txt中的路径再用这个路径去读取name.txt的内容,代码如下。const fs = require('fs') //导入node中的文件模块 fs.readFile('./age.txt', 'utf8', function(err, data){ if(err) throw new Error(err) fs.readFile(data,'utf8',function (err,data) { if(err) throw new Error(err) console.log(data) }) }) - 假如有多个文件这样嵌套呢,那我们的代码就会变成这样,也就是我们所说的回调地狱。
fs.readFile('./age.txt', 'utf8', function(err, data){ if(err) throw new Error(err) fs.readFile(data,'utf8',function (err,data) { if(err) throw new Error(err) fs.readFile(data,'utf8',function (err,data) { if(err) throw new Error(err) fs.readFile(data,'utf8',function (err,data) { if(err) throw new Error(err) fs.readFile(data,'utf8',function (err,data) { if(err) throw new Error(err) console.log(data) }) }) }) }) }) - 那么
Promise作为一种异步编程的解决方案,它是如何解决回调地狱这种情况的呢,我们来看代码。- 首先我们将
readFile的方法封装成promise
const readFile = (filePath) => { return new Promise((resolve,reject)=>{ fs.readFile(filePath,'utf8',function (err,data) { if(err) {// 失败了调用reject return reject(err); } resolve(data); // 成功调用resolve }) }) }- 用我们封装后的
readFile再去读取age.txt,name.txt的内容,编写代码就很友好了。
readFile('./age.txt').then(data => { return readFile(data) }).then(data => { console.log(data) },reason => { console.log(reason) })- 如愿以偿得到了我们想要的结果
- 首先我们将