源码取自:源码博客javascript
源码:html
class Promise2 { constructor(executor) { //executor执行器 this.status = 'pending'; //默认等待状态 this.value = undefined; //成功的值 this.reason = undefined //失败的原用 this.onResovleCallbacks = []; this.onRejectedCallbacks = []; let resolve = (value) => { if (this.status === 'pending') { this.status = 'resolved'; //成功 this.value = value; this.onResovleCallbacks.forEach(fn => fn()); } } let reject = (reason) => { if (this.status === 'pending') { this.status = 'rejected'; //失败 this.reason = reason; this.onRejectedCallbacks.forEach(fn => fn()); } } try { executor(resolve, reject); //默认上执行器执行 } catch (e) { //捕获到异常时,直接走失败 reject(e); } } then (onFufilled, onRejected) { onFufilled = typeof onFufilled === 'function' ? onFufilled : value => value; onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }; function resolvePromise (promise2, x, resolve, reject) { //x多是别人的 promise ,因此尽量的容许别人瞎写 if (promise2 === x) { //返回的结果和promise是同一个,那么永远不会成功 return reject(new TypeError('循环引用')); } // let called; // 看x是否是promise。promise应该是一个对象 if (x != null && (typeof x === 'object' || typeof x === 'function')) { //多是promise try { let then = x.then; // 若是是对象 我就试着取一下then方法 若是有then,认为它是promise if (typeof then === 'function') { // then是函数,是promise then.call(x, y => { // 成功和失败只能调用一个 if (called) return; called = true; // resolve的结果依旧是promise 那就继续解析 resolvePromise(promise2, y, resolve, reject); }, r => { if (called) return; called = true; reject(r); // 失败了就失败了 }) } else { resolve(x); // 直接成功便可 } } catch (e) { // 取then出错了那就不要在继续执行了 if (called) return; called = true; reject(e); } } else { //普通值 让promise2直接变成成功态 resolve(x); } }; let promise2; //返回的新promise promise2 = new this.constructor((resolve, reject) => { if (this.status === 'resolved') { // setTimeout(() => { try { let x = onFufilled(this.value); //x是上一个promise返回值,多是一个普通值,也多是一个promise;x也多是别人的promise,咱们能够写一个方法,统一处理 resolvePromise(promise2, x, resolve, reject); //下一次then的实例promise2,此次返回值x,promise2的成功方法,promise2的失败方法 } catch (e) { reject(e) } // }, 0); } if (this.status === 'rejected') { // setTimeout(() => { try { let x = onRejected(this.reason); // reject(x); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e) } // }, 0) } if (this.status === 'pending') { this.onResovleCallbacks.push(() => { // setTimeout(() => { try { let x = onFufilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } // }, 0) }); this.onRejectedCallbacks.push(() => { // setTimeout(() => { try { let x = onRejected(this.reason) resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } // }, 0) }) } }); return promise2; } catch (onRejected) { return this.then(null, onRejected); } finally (onFinally) { return this.then(function (value) { return Promise.resolve(onFinally(value)) }, function (reason) { return Promise.resolve(onFinally(reason)) }); } static resolve (data) { return new this((resovle) => { resovle(); }).then(_ => { return data; }) } static reject (data) { /* 与原生保持一致 */ return new this((resolve, reject) => { reject(data); }); /* 与Promise.resovle保持一致 */ return new this((resolve, reject) => { reject(); }).then(_ => { return data; }) } static all (arr) { arr = Object.prototype.toString.call([]) === "[object Array]" ? arr : [arr]; let length = arr.length; if (!length) return; return new this((resolve, reject) => { let result = []; let num = length; arr.forEach((item, index) => { /* 将item包装为promise */ return new this(r => r()) .then(_ => item) .then(_ => { result[index] = _; num--; num === 0? resolve(result):null; }, _ => { reject(_); }) }) }) } static race(arr){ arr = Object.prototype.toString.call([]) === "[object Array]" ? arr : [arr]; let length = arr.length; if (!length) return; return new this((resolve,reject)=>{ arr.forEach(item=>{ new this(r=>r()).then(_=>item) .then(_=>{ resolve(_); },_=>{ reject(_); }) }) }) } }
Promise:java
1. 为了实现promise的链式调用,每一次的then,finally或catch后返回的都是一个全新的promise.promise
2.因为1的缘由,状态凝固也只在当前的promise中有效。函数
3.因为1的缘由,promise中的resolveArrs的长度老是<=1,rejectArrs同理。this
4.then方法是promise的核心,then的回调的方法:
首先将返回值包装为一个promise,需排除回调方法不是当前promise自己,而后递归执行此promise,至为普通返回值,直接resolve(onResolve),或reject(onReject)
5. catch,finally 为then方法的特殊状况prototype
6. 链式中的then为微任务,须要所有早于当前周期中的全部setTimeout执行,全部不能加setTimeout;
若不加,同时会带来另外一个问题:同一周期内此promise的then方法将所有提早于全部原生promise的then方法执行,不过不会出现即便有原生方法又使用此补丁的状况。
二者比较,取后者影响更小code
7.Promise.resolve(data).then():data为常量或Promise,data为promise时, 状态会被data所改变,then中获取的为promise执行的结果htm
8.Promise.reject(data):data为常量或Promise,data为promise时,状态会被data所改变,then中获取的为promise自己对象