Promise 是异步编程的一种解决方案,用于解决传统编程中的回调地狱问题。ES6对其标准用法进行了统一,并原生提供了Promise对象。Promise对象有三种状态:等待态(Pending)、执行态(Fulfilled)和拒绝态(Rejected),且状态的转换是不可逆的,只能由Pending转换为Fulfilled或Rejected,而Fulfilled和Rejected之间是不能互相转换的。
Promise对象表示一个异步操作的执行结果,通过then方法与其进行交互,then方法使用两个回调函数作为参数,用于接收Promise成功执行的结果或者被拒绝执行的原因。
基本用法:
function onFulfilled(value) { console.log(value) } function onRejected(error) { console.log(error) } const promise = new Promise(function(resolve, reject) { // ...异步操作 if (/* 操作成功 */) { resolve(value); } else { reject(error); } }); promise.then(onFulfilled, onRejected);
上面就是Promise的一个基本用法,更详细的使用说明请参考阮一峰ECMAScript 6入门之Promise对象。
原理说明:
通过上面的基本用法可以看出,Promise是一个构造函数,该构造函数接收一个函数作为参数,为了便于说明我们把该函数命名为executor,executor有两个参数resolve和reject,这两个参数也都是函数。Promise对象上还必须有一个then方法,该方法也接收两个函数作为参数。
基于以上说明,我们先给出一个Promise构造函数的简单实现框架如下:
function Promise(executor) { function resolve(value) {
} function reject(error) {
} executor(resolve, reject) } Promise.prototype.then = function(onFulfilled, onRejected) {
}
而Promise的核心特点之一就是状态的转换,所以我们要在框架中体现出转换的变化,如下:
function Promise(executor) { this.status = 'pending' function resolve(value) { if(this.status == 'pending') { this.status = 'fulfilled' } } function reject(error) { if(this.status == 'pending') { this.status = 'rejected' } } executor(resolve, reject) } Promise.prototype.then = function(onFulfilled, onRejected) { if(this.status == 'fulfilled') { onFulfilled() } if(this.status == 'rejected') { onRejected() } }
此时该Promise也仅仅只是能够处理同步操作,就是说当我们调用then方法时executor已经处理结束,状态已经由pending转换为fulfilled或rejected,但这肯定是不可以的!!!所以在调用then方法时我们还得考虑状态为pending的情况,但是在状态为pending的情况下调用onFulfilled或onRejected回调函数是完全没有意义的,所以我们只能先将对应的回调函数缓存起来,等到状态改变之后再调用执行。如下:
function Promise(executor) { this.status = 'pending' this.value = null this.error = null this.onFulfilledCallbacks = [] this.onRejectedCallbacks = [] function resolve(value) { if(this.status == 'pending') { this.status = 'fulfilled' this.value = value this.onFulfilledCallbacks.forEach(function(callback) { callback() }); } } function reject(error) { if(this.status == 'pending') { this.status = 'rejected' this.error = error this.onRejectedCallbacks.forEach(function(callback) { callback() }); } } executor(resolve, reject) } Promise.prototype.then = function(onFulfilled, onRejected) { if(this.status == 'fulfilled') { onFulfilled(this.value) } if(this.status == 'rejected') { onRejected(this.error) } if(this.status == 'pending') { this.onFulfilledCallbacks.push(onFulfilled(this.value)) this.onRejectedCallbacks.push(onRejected(this.error)) } }
至此,一个简单的Promise实现就算完成了,暂时没有考虑一些校验和错误处理。其实核心的实现原理就是状态机制+观察者模式。
参考文献: