前言
Promise是异步操作中最常用的一种模式,这篇文章我们探讨一下如何基于Promise/A规范实现一个Promise,完整实现采用ES5语法,运行环境为Node.js,使用process.nextTick实现推迟then指定的回调函数的执行。
简化后的Promise/A规范
查阅了一下Promise/A规范,总结出来了一下几个要求,Promise的功能基于以下几个要求来实现
- 使用new Promise创建一个对象,参数为一个方法,传入的方法有两个参数
- Promise.then方法为指定的Promise回调之后调用的方法,这个参数方法可以有一个参数,也可以有两个参数
- Promise.catch方法指定失败回调
- Promise.then和Promise.catch的返回值都是一个Promise,如果在回调函数中指定了返回的Promise,则返回这个promise,否则返回一个新的状态为 resolved的promise
- Promise有三种状态,分别是penging、resolved、rejected,如果状态改变成resolved或者rejected则无法再发生变化
- 使用Promise.then指定的回调函数,回调函数会在当前的同步代码执行完成后执行,如果Promise的状态已经是resolved,则回调也会推迟到下一次微事件循环时执行
- 同一个promise对象可以指定多个回调函数,这些回调函数的执行顺序按照声明的时候的顺序来执行
开始实现
根据Promise的使用经验,我们很容易的给出如下的代码结构:
function MyPromise(fn){
// 私有方法
function resolve(value){
}
function reject(value){
}
// 公有方法
this.then = function(fn){
}
this.catch = function(fn){
}
this.finally = function(fn){
}
fn.call(global, resolve, reject); // 调用fn方法,并将resolve和reject作为参数传进去
}
然后MyPromise有三种状态,和一个值,添加这两个私有变量。然后同一个promise可以添加多个then、catch回调,这是我们需要用一个回调函数队列来实现。
改变后的代码结构如下:
function MyPromise(fn){
// 私有属性
var __status = 'pending';
var __data;
var resolveCallbacks = new Array();
var rejectCallbacks = new Array();
var finallyCallback;
// 私有方法
function resolve(value){
}
function reject(value){
}
// 公有方法
this.then = function(fn){
}
this.catch = function(fn){
}
this.finally = function(fn){
}
fn.call(global, resolve, reject); // 调用