You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
classMyPromise{constructor(executor){if(!this._isFunction(executor)){thrownewError(`Promise resolver ${executor} is not a function`);}}_isFunction(val){returnObject.prototype.toString.call(val)==='[object Function]';}_resolve(){}_reject(){}}
classMyPromise{constructor(executor){if(!this._isFunction(executor)){thrownewError(`${executor} is not a function`);}this._status="pending";this._value=undefined;this._handleFulfilled=[];this._handleRejected=[];// 很多文章在这里给executor加了try catch,实际上原生Promise的executor中的错误并没有捕获executor(this._resolve.bind(this),this._reject.bind(this));}_isFunction(val){returnObject.prototype.toString.call(val)==="[object Function]";}_resolve(value){if(this._status==='pending'){this._status="fulfilled";this._value=value;letcb;// 异步按顺序调用并清空回调setTimeout(()=>{while(cb=this._handleFulfilled.shift()){cb(value);}},0)}}_reject(value){if(this._status==='pending'){this._status="rejected";this._value=value;letcb;// 异步按顺序调用并清空回调setTimeout(()=>{while((cb=this._handleRejected.shift())){cb(value);}},0);}}}
Promise标准
不能免俗地贴个Promise标准链接Promises/A+。ES6的Promise有很多方法,包括Promise.all()/Promise.resolve()/Promise.reject()等,但其实这些都是Promises/A+规范之外的,Promises/A+规范只定义了一个Promise.then()方法,这是Promise的核心。
基本结构
Promise接收一个函数作为参数,我们称之为executor,该函数有两个参数resolve和reject,这两个参数也都是函数,并且,它们定义在Promise内部。
那么我们定义一个class并定义一个_isFunction方法,用来校验构造函数的参数必须是函数。再定义resolve和reject这两个方法。
Promise状态、resolve、reject
Promise有三种状态,分别是pending(等待中)、fulfilled(成功)、rejected(失败)。状态改变只能从pending => fulfilled,或者pending => rejected。
resolve的作用,就是将Promise的状态从pending改为fulfilled,它接收一个参数作为Promise执行成功的值,这个值会传给then的第一个回调函数。reject的作用是将Promise的状态从pending改为rejected,它也接收一个参数作为Promise执行失败的值,这个值会传给then的第二个回调函数。
那么我们定义好状态_status、_resolve、_reject,再定义两个数组_handleFulfilled、_handleRejected,分别存放then的成功和失败回调集合。当用户调用resolve或reject方法后,开始异步调用_handleFulfilled或_handleRejected数组中的回调。
Promise.then
Promise.then定义了两个回调onFulfilled和onRejected
它们分别在Promise执行成功/失败时执行,它们都是可选的,Promises/A+规范规定,如果onFulfilled或onRejected不是函数,将被忽略,Promise会继续执行下一个then的回调。比如下面的例子会输出1,.then(2)则被忽略了。
then可以链式调用,是因为每个then都会返回一个新的Promise。为什么要返回新的Promise?因为每个then都可以返回不同的值,如果用同一个Promise,状态变化后是不能再修改的,无法做到返回不同的值。
then的回调执行onFulfilled还是onRejected,取决于Promise的状态,如果Promise状态为pending,只会将onFulfilled和onRejected分别push到_handleFulfilled和_handleRejected数组;如果状态为fulfilled,会执行对应的onFulfilled;如果状态是rejected,执行对应的onRejected;
那么then方法的基本结构如下
在then链式调用的情况下,如果前一个then返回的是一个新Promise,后一个then的回调必须等这个新Promise的状态改变后才会执行。举例,下面的代码输出1之后,等待3秒才会输出2:
因此要对then的回调函数的返回值做个判断,如果返回值不是Promise,利用resolve直接返回这个值;如果返回值是Promise,就要等这个Promise状态变化之后再返回,而Promise状态变化之后一定会调用then的回调函数,利用这个特性,将resolve、reject作为then的回调函数即可。
完整代码
测试一下,先输出1,3秒后输出2,说明MyPromise的基本功能没问题了。
最后,总结一下,Promise是如何实现异步编程的?
Promise接收一个函数为参数,传入了两个内部的方法resolve和reject,然后用then注册回调函数,手动调用resolve或reject就可以依次执行then的回调,并且给回调函数传值。如果then返回的也是Promise,同样的,手动调用resolve或reject后,才会继续往下执行。
其实本质上还是回调函数,只不过写法变了。
The text was updated successfully, but these errors were encountered: