简单实现一个Promise A+ 规范的Promise
首先,了解一下Promise的基本用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 const promise = new Promise ((resolve, reject ) => { if () { resolve ('成功回调' ) }else { reject ('失败回调' ) } }); promise.then (res => { console .log ('成功回调' ) }, err => { console .log ('失败回调' ) })
通过上述用法,可以看出来Promise 接受一个执行器函数作为参数,这个函数带有两个参数
resolve:把 Promise 状态改成成功
reject:把 Promise 状态改成失败
promise的状态有三种,分别是:
pending 默认状态
fulfilled 成功,返回成功值
rejected 失败,返回失败值
promise的状态是单向流动的,且一旦成功和失败,状态不可改变
下面我们可以简单实现一下基本特性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 const STATUS = { PENDING : 'pending' , FULFILLED : 'fulfilled' , REJECTED : 'rejected' } class MyPromise { construtor (executor ) { executor (this .resolve , this .reject ) } status = STATUS .PENDING value = null ; reason = null ; resolve = value => { if (this .status == STATUS .PENDING ){ this .status = STATUS .fulfilled ; this .value = value; } } reject = reason => { if (this .status == STATUS .PENDING ){ this .status = STATUS .REJECTED ; this .reason = reason; } } }
除此之外,Promise.then 还分别接收两个回调
1 Promise .then (onFulfilled, onRejected);
其中 onFulfilled
要求如下:
必须在 promise 状态为完成时调用它,并将 promise 的 value 作为它的第一个参数
在 promise 完成之前不能调用它
它不能被多次调用
onRejected
要求如下:
必须在 promise 被拒绝后调用它,以 promise.reason 作为它的第一个参数
在 promise 被拒绝之前不能调用它
它不能被多次调用
于是我们继续补充 MyPromise
1 2 3 4 5 6 7 8 9 10 11 12 13 class MyPromise { ... ... then (onFulfilled, onRejected ){ if (this .status == STATUS .FULFILLED ){ onFulfilled (this .value ); }else if (this .status == STATUS .REJECTED ){ onRejected (this .reason ); } } }
至此 一个简单的 MyPromise
就完成了 实验一下
1 2 3 4 5 6 7 8 9 10 const mypromise = new MyPromise ((resolve, reject ) => { resolve ('成功' ) }) mypromise.then (data => { console .log (data, '请求成功' ) }, err => { console .log (err, '请求失败' ) })
成功了
接着,根据 Promise A+
规范继续完善 MyPromise.then
2.2.1 Both onFulfilled and onRejected are optional arguments: 2.2.1.1 If onFulfilled is not a function, it must be ignored. 2.2.1.2 If onRejected is not a function, it must be ignored.
简单说,就是 Promise.then
接受的 onFulfilled
、onRejected
是可选的。如果 onFulfilled
不是函数,他必须被忽略。如果 onRejected
不是函数,也必须被忽略。
那么,我们在这里加个判断
1 2 3 4 5 6 7 8 9 10 class MyPromise { ... ... then (onFulfilled, onRejected ){ onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value onRejected = typeof onRejected === 'function' ? onRejected : error => { throw error } } }
then 可以在同一个承诺上多次调用
当 promise 完成,所有相应的 onFulfilled 回调必须按照它们的原始调用的顺序执行 then
当 promise 被拒绝,所有相应的 onRejected 回调必须按照它们对 的原始调用的顺序执行 then
可以理解为将 onFulfilled、onRejected 作为数组存储在 MyPromise 中,然后按照顺序执行
如下图,新增了成功回调跟失败回调
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class MyPromise { onFulfilledCallback = [] onRejectedCallback = [] resolve = value => { if (this .status === STATUS .PENDING ) { this .status = STATUS .FULFILLED this .value = value while (this .onFulfilledCallback .length ) { this .onFulfilledCallback .shift ()(value) } } } reject = value => { if (this .status === STATUS .PENDING ) { this .status = STATUS .REJECTED this .reason = value while (this .onRejectedCallback .length ) { this .onRejectedCallback .shift ()(value) } } } then = function (onFulfilled, onRejected ) { onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason } if (this .status === STATUS .PENDING ) { this .onFulfilledCallback .push (onFulfilled) this .onRejectedCallback .push (onRejected) } else if (this .status === STATUS .FULFILLED ) { onFulfilled (this .value ) } else if (this .status === STATUS .REJECTED ) { onRejected (this .reason ) } } }
then 必须返回一个 Promise 来支持链式调用 Promise
then 方法需要返回 MyPromise 实例
then 内部调用回调时,需通过 resolvePromise 方法判断返回值 x 的类型来处理返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class MyPromise { then = function (onFulfilled, onRejected ) { const promise2 = new MyPromise ((resolve, reject ) => { if (this .status === STATUS .PENDING ) { const value = onFulfilled (this .value ) this .onFulfilledCallback .push (() => { resolvePromise (promise2, value, resolve, reject) }) const reason = onRejected (this .value ) this .onRejectedCallback .push (() => { resolvePromise (promise2, reason, resolve, reject) }) } else if (this .status === STATUS .FULFILLED ) { const value = onFulfilled (this .value ) resolvePromise (promise2, value, resolve, reject) } else if (this .status === STATUS .REJECTED ) { const error = onRejected (this .error ) resolvePromise (promise2, error, resolve, reject) } }) return promise2 } }
上述代码引用了 resolvePromise 来处理 Promise.then 的返回值
如果 promise2 === x, 执行 reject,错误原因为 TypeError
如果 x 是函数或对象
如果 x.then 是函数
如果 x.then 不是函数
如果 x 不是函数或对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 function resolvePromise (promise2, x, resolve, reject) { if (promise2 === x) { reject (new TypeError ('The promise and the return value are the same' )) } if (typeof x === 'object' || typeof x === 'function' ) { let then try { then = x.then } catch (error) { reject (error) } if (typeof then === 'function' ) { then.call (x, y => { resolvePromise (promise2, y, resolve, reject); }, err => { reject (err); }) } else { resolve (x) } } else { resolve (x) } }
好了