手写Promise,全部测试通过!
promises-aplus-tests
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MPromise {
constructor(ex) {
this.state = PENDING;
this.value = undefined;
this.reason = undefined;
this.rejCallbacks = [];
this.resCallbacks = [];
const resolve = (val) => {
if (this.state === PENDING) {
this.state = FULFILLED;
this.value = val;
this.resCallbacks.map(fn => fn());
}
}
const reject = (val) => {
if (this.state === PENDING) {
this.state = REJECTED;
this.value = val;
this.rejCallbacks.map(fn => fn());
}
}
try {
ex(resolve, reject)
} catch (e) {
reject(e)
}
}
then(OnFullfill, OnReject) {
/**
* 如果传入非函数参数,将参数变成函数
*/
OnFullfill = typeof OnFullfill === 'function' ? OnFullfill : val => val;
OnReject = typeof OnReject === 'function' ? OnReject : val => { throw val }
/**
* then是异步执行的,then的所有执行会放到下一次事件循环,其中x是上一次then的返回值
*/
let promise2 = new MPromise((resolve, reject) => {
if (this.state === FULFILLED) {
setTimeout(() => {
try {
let x = OnFullfill(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
})
}
if (this.state === REJECTED) {
setTimeout(() => {
try {
let x = OnReject(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
})
}
if (this.state === PENDING) {
this.resCallbacks.push(() => {
setTimeout(() => {
try {
let x = OnFullfill(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
})
});
this.rejCallbacks.push(() => {
setTimeout(() => {
try {
let x = OnReject(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
})
});
}
})
return promise2;
}
}
function resolvePromise(promise2, x, resolve, reject) {
/**
* 循环引用,p1=new Promise(...) ; p2 = p1.then(r=>{return p2})
*/
if (promise2 === x) {
reject(new TypeError('Chaining cycle'))
}
/**
* 解决then返回promise resolve({then:...}) resolve(new Promise(function(res,rej)=>{...}))
*/
if (x && typeof x === 'object' || typeof x === 'function') {
let used;
try {
/**
* 难点,解决thenable方法的处理
*/
let then = x.then
/**
* 当上一次then传递过来的then,used变量用于确保回调时两种状态只执行一种
*/
if (typeof then === 'function') {
then.call(x, (y) => {
/**
* y是resolve的值
* new Promise(function(resovle,reject){
* resolve(1)
* }).then(x=>{
* return(new Promise(...))
* })
* 下面这个then call的是120行的Promise的then
* 解释:如果120行return的是一个Promise对象,包含了then方法,
* 在调用then时,会调用120行的Promise的then方法,它的then第一个参数是这里的y,
* 即是它resolve的值,resolve的结果最终会传给顶层的resolve解决
* 这里把y和promise2传递下去执行
* 下面的then不是120行的then,但是是120行then调用后resolve的结果
* .then(xpromise=>{
* console.log(xpromise) //是上一个Promise resolve的值,不是一个Promise
* })
*/
if (used) return;
used = true;
resolvePromise(promise2, y, resolve, reject);
}, (r) => {
if (used) return;
used = true;
reject(r);
})
}
/**
* then不是函数,直接resolve x
*/
else {
resolve(x)
}
} catch (e) {
if (used) return;
used = true
reject(e)
}
} else {
resolve(x)
}
}
MPromise.defer = MPromise.deferred = function () {
let dfd = {};
dfd.promise = new MPromise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
}
module.exports = MPromise;