一,前言
上一篇,翻译并理解了整个 Promise A+ 规范;
本篇开始,将基于 Promise A+ 规范,对我们的简版 Promise 源码进行功能完善;
本篇,将实现 Promise 对异步操作的支持;
二,前文回顾
在前面几篇中,结合对 Promise 基础功能的使用介绍和简单分析,手写了一个简版 Promise 源码,主要覆盖了以下几点:
promise 是一个类;
使用 promise 时,传入 executor 执行器,并被立即执行;
executor 参数是两个函数,用于描述 promise 实例的状态;
resolve 表示成功,可以传入一个 value;
reject 表示失败,可以传入一个 reason;
每个 Promise 实例都有一个 then 方法;
promise 一旦状态发生后,不能再更改;
promise 有三种状态:成功态,失败态,等待态(默认);
简版源码如下:
const PENDING = 'PENDING'; // 等待态
const DULFILLED = 'DULFILLED'; // 成功态
const REJECTED = 'REJECTED'; // 失败态
class Promise{
// 通过 new Promise 进行实例化时,传入 executor 执行器函数
constructor(executor){
this.value = undefined; // 保存成功的原因,then中调用onFulfilled时传入
this.reason = undefined; // 保存失败的原因,then中调用onFulfilled时传入
this.state = PENDING; // promise 状态,默认等待态
// 成功 reslove 函数、失败reject函数,并传入executor
const reslove = (value) =>{
// 等待态 --> 成功态
if(this.state === PENDING){
this.value = value
this.state = DULFILLED;
}
}
const reject = (reason) =>{
// 等待态 --> 失败态
if(this.state === PENDING){
this.reason = reason
this.state = REJECTED;
}
}
// 立即执行 executor 执行器函数,通过 try...catch... 进行异常捕捉;
try{
executor(reslove, reject);
}catch(e){
reject(e) // 有异常,调用 reject 更新为失败态
}
}
// 定义 then 方法:包含两个参数 onFulfilled 和 onRejected;
// 根据 Promise 状态,执行 onFulfilled 或 onRejected;
then(onFulfilled, onRejected){
// 成功态,调用 onFulfilled,传入成功 value
if(this.state === DULFILLED){
onFulfilled(this.value)
}
// 失败态,执行 onRejected,传入失败 reason
if(this.state === REJECTED){
onRejected(this.reason)
}
}
}
module.exports = Promise;
复制代码
三,提出问题
前面说,Promise 的一个主要作用就是处理异步操作,使开发者使用同步编程方式处理异步操作,相比之前 callback 回调的处理方式,能够更好的解决/避免回调地狱的产生,同时还能实现控制权的反转;
1,测试原生 Promise
使用原生 Promise 执行异步操作:
let promise = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('ok');
}, 1000)
})
promise.then((value)=>{
console.log('success', value)
},(reson)=>{
console.log('err',reson)
})
// success ok
复制代码
2,测试手写 Promise
// 引入手写的 promise.js
let promise = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('ok');
}, 1000)
})
promise.then((value)=>{
console.log('success', value)
},(reson)=>{
console.log('err',reson)
})
复制代码
执行结果将不会输出任何内容,即 then 中的成功回调 onFulfilled 和失败回调 onRejected 都没有被执行;
3,问题分析
执行过程分析:
当 new Promise 完成后,executor 执行器函数被立即执行,定时器被启动;
promise.then 被执行,当前 promise 实例状态为 pending 态,不执行任何操作;
1 秒后定义器回调执行,调用 resolve,将当前 promise 实例状态更新为成功态;
问题原因:
4,解决方案
这种“先收集,再执行”的功能特征,符合订阅发布模式;
四,实现 Promise 对异步操作的支持
1,事件订阅:收集回调函数
class Promise{
constructor(executor){
this.state = PENDING;
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = []; // 收集成功回调
this.onRejectedCallbacks = []; // 收集失败回调
// ...
}
then(onFulfilled, onRejected){
// 执行异步操作时,收集成功/失败回调
if(this.state === PENDING){
this.onResolvedCallbacks.push(()=>{
onFulfilled(this.value) // 传入 value
})
this.onRejectedCallbacks.push(()=>{
onRejected(this.value) // 传入 value
})
}
// ...
}
}
复制代码
这样,就完成了成功/失败回调函数的事件订阅操作;
2,事件发布:根据状态执行回调处理
当 Promise 中的 resolve 或 reject 函数被调用时,根据状态执行对应的回调处理:
class Promise{
constructor(executor){
this.state = PENDING;
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
const reslove = (value) =>{
if(this.state === PENDING){
this.value = value
this.state = DULFILLED;
// 事件发布操作
this.onResolvedCallbacks.forEach(fn=>fn())
}
}
const reject = (reason) =>{
if(this.state === PENDING){
this.reason = reason
this.state = REJECTED;
// 事件发布操作
this.onRejectedCallbacks.forEach(fn=>fn())
}
}
// ...
}
// ...
}
复制代码
这里相当于“订阅发布模式”中的事件发布;
3,测试对异步操作的支持
let promise = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('ok');
}, 1000)
})
promise.then((value)=>{
console.log('success', value)
},(reson)=>{
console.log('err',reson)
})
// success ok
复制代码
五,结尾
本篇,主要实现了 Promise 对异步操作的支持,主要涉及以下几个点:
测试 Promise 对异步操作的支持;
分析当前 Promise 代码问题及解决方案;
使用发布订阅思想实现对异步操作的支持;
Promise 异步操作的测试;
下一篇,实现 Promise 的链式调用;
评论