Promise关键代码实现
基础逻辑实现
TIP
Promise
一共有三种状态status
:Pending
,Fulfilled
以及Rejected
。
Promise
初始状态为PENDING
,如果Promise
处于Pending
,resolve
后,进入Fulfilled
状态,reject
则进入Rejected
状态。
定义完Promise
类后,then
方法包含onFulFilled
与onRejected
两个回调函数,根据status
判断。
1. 基础结构
// 基础结构
// const promise = new MyPromise((resolve, reject) => {
// resolve('success');
// reject('fail');
// });
// MyPromise.js
class MyPromise {
constructor(executor) {
executor(resolve, reject);
}
resolve = () => {};
reject = () => {};
}
if (typeof module !== "undefined" && module.exports) {
// 在 Node.js 环境中
module.exports = MyPromise;
}
// 基础结构
// const promise = new MyPromise((resolve, reject) => {
// resolve('success');
// reject('fail');
// });
// MyPromise.js
class MyPromise {
constructor(executor) {
executor(resolve, reject);
}
resolve = () => {};
reject = () => {};
}
if (typeof module !== "undefined" && module.exports) {
// 在 Node.js 环境中
module.exports = MyPromise;
}
2. 状态转换
// 定义三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject);
}
// 存储成功的参数
res = null;
// 存储失败的参数
err = null;
// 初始状态
status = PENDING;
resolve = (res) => {
// 如果成功且状态为PENDING
if(this.status === PENDING) {
this.status = FULFILLED;
this.res = res;
}
};
reject = (err) => {
if(this.status === PENDING) {
this.status = REJECTED;
this.err = err;
}
};
}
// 定义三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject);
}
// 存储成功的参数
res = null;
// 存储失败的参数
err = null;
// 初始状态
status = PENDING;
resolve = (res) => {
// 如果成功且状态为PENDING
if(this.status === PENDING) {
this.status = FULFILLED;
this.res = res;
}
};
reject = (err) => {
if(this.status === PENDING) {
this.status = REJECTED;
this.err = err;
}
};
}
3. then()方法实现
// 定义三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject);
}
// ...
then(onFulfilled, onRejected) {
if(this.status === FULFILLED) {
onFulfilled(this.res);
} else if(this.status === REJECTED) {
onRejected(this.err);
}
}
}
// 定义三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject);
}
// ...
then(onFulfilled, onRejected) {
if(this.status === FULFILLED) {
onFulfilled(this.res);
} else if(this.status === REJECTED) {
onRejected(this.err);
}
}
}
核心逻辑代码与测试
// 定义三种状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject);
}
// 存储成功的参数
res = null;
// 存储失败的参数
err = null;
// 初始状态
status = PENDING;
resolve = (res) => {
// 如果成功且状态为PENDING
if (this.status === PENDING) {
this.status = FULFILLED;
this.res = res;
}
};
reject = (err) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.err = err;
}
};
then(onFulfilled, onRejected) {
if (this.status === FULFILLED) {
onFulfilled(this.res);
} else if (this.status === REJECTED) {
onRejected(this.err);
}
}
}
if (typeof module !== "undefined" && module.exports) {
// 在 Node.js 环境中
module.exports = MyPromise;
}
// 定义三种状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject);
}
// 存储成功的参数
res = null;
// 存储失败的参数
err = null;
// 初始状态
status = PENDING;
resolve = (res) => {
// 如果成功且状态为PENDING
if (this.status === PENDING) {
this.status = FULFILLED;
this.res = res;
}
};
reject = (err) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.err = err;
}
};
then(onFulfilled, onRejected) {
if (this.status === FULFILLED) {
onFulfilled(this.res);
} else if (this.status === REJECTED) {
onRejected(this.err);
}
}
}
if (typeof module !== "undefined" && module.exports) {
// 在 Node.js 环境中
module.exports = MyPromise;
}
const MyPromise = require("./myPromise");
const promise = new MyPromise((resolve, reject) => {
// resolve("成功"); // 输出 onFulfilled 成功
reject("失败"); // 输出 onRejected 失败
});
promise.then(
(res) => {
console.log(`onFulfilled ${res}`);
},
(err) => {
console.log(`onRejected ${err}`);
}
);
const MyPromise = require("./myPromise");
const promise = new MyPromise((resolve, reject) => {
// resolve("成功"); // 输出 onFulfilled 成功
reject("失败"); // 输出 onRejected 失败
});
promise.then(
(res) => {
console.log(`onFulfilled ${res}`);
},
(err) => {
console.log(`onRejected ${err}`);
}
);
加入异步逻辑
现在调用的方式改为setTimeout
异步的方式
const MyPromise = require("./myPromise");
const promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
// resolve("成功");
reject("失败");
});
});
promise.then(
(res) => {
console.log(`onFulfilled ${res}`);
},
(err) => {
console.log(`onRejected ${err}`);
}
);
const MyPromise = require("./myPromise");
const promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
// resolve("成功");
reject("失败");
});
});
promise.then(
(res) => {
console.log(`onFulfilled ${res}`);
},
(err) => {
console.log(`onRejected ${err}`);
}
);
此时发现,输出为空。
原因在于:
then
是同步方法,调用then
的时候,setTimeout
作为宏任务还没有执行,那么promise.status === Pending
,既不会走onFulfilled
也不会走onRejected
。解决方法:因此,我们只需要在
then
添加新的逻辑,当状态仍为Pending
的时候单独处理,存储onFulfilled
与onRejected
作为回调的函数callback
,当转换状态的时候,执行对应的回调函数onFulfilledCallback/onRejectedCallback
// MyPromise.js
// ...
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject);
}
// 存储成功的参数
res = null;
// 存储失败的参数
err = null;
// 初始状态
status = PENDING;
// 存储成功/失败的回调函数
onFulfilledCallback = null;
onRejectedCallback = null;
resolve = (res) => {
// 如果成功且状态为PENDING
if (this.status === PENDING) {
this.status = FULFILLED;
this.res = res;
// 如果有成功的回调函数就执行
this.onFulfilledCallback && this.onFulfilledCallback(res);
}
};
reject = (err) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.err = err;
// 如果有失败的回调函数就执行
this.onRejectedCallback && this.onRejectedCallback(err);
}
};
then(onFulfilled, onRejected) {
if (this.status === FULFILLED) {
onFulfilled(this.res);
} else if (this.status === REJECTED) {
onRejected(this.err);
} else if (this.status === PENDING) {
this.onFulfilledCallback = onFulfilled;
this.onRejectedCallback = onRejected;
}
}
}
if (typeof module !== "undefined" && module.exports) {
// 在 Node.js 环境中
module.exports = MyPromise;
}
// MyPromise.js
// ...
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject);
}
// 存储成功的参数
res = null;
// 存储失败的参数
err = null;
// 初始状态
status = PENDING;
// 存储成功/失败的回调函数
onFulfilledCallback = null;
onRejectedCallback = null;
resolve = (res) => {
// 如果成功且状态为PENDING
if (this.status === PENDING) {
this.status = FULFILLED;
this.res = res;
// 如果有成功的回调函数就执行
this.onFulfilledCallback && this.onFulfilledCallback(res);
}
};
reject = (err) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.err = err;
// 如果有失败的回调函数就执行
this.onRejectedCallback && this.onRejectedCallback(err);
}
};
then(onFulfilled, onRejected) {
if (this.status === FULFILLED) {
onFulfilled(this.res);
} else if (this.status === REJECTED) {
onRejected(this.err);
} else if (this.status === PENDING) {
this.onFulfilledCallback = onFulfilled;
this.onRejectedCallback = onRejected;
}
}
}
if (typeof module !== "undefined" && module.exports) {
// 在 Node.js 环境中
module.exports = MyPromise;
}
多次调用then
两个🌰
const MyPromise = require("./myPromise");
const promise = new MyPromise((resolve, reject) => {
resolve("成功");
});
promise.then(
(res) => {
console.log(`onFulfilled ${res}`);
},
(err) => {
console.log(`onRejected ${err}`);
}
);
promise.then(
(res) => {
console.log(`onFulfilled 2`);
},
(err) => {
console.log(`onRejected 2`);
}
);
// 输出:
// onFulfilled 成功
// onFulfilled 2
const MyPromise = require("./myPromise");
const promise = new MyPromise((resolve, reject) => {
resolve("成功");
});
promise.then(
(res) => {
console.log(`onFulfilled ${res}`);
},
(err) => {
console.log(`onRejected ${err}`);
}
);
promise.then(
(res) => {
console.log(`onFulfilled 2`);
},
(err) => {
console.log(`onRejected 2`);
}
);
// 输出:
// onFulfilled 成功
// onFulfilled 2
const MyPromise = require("./myPromise");
const promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
reject("失败");
});
});
promise.then(
(res) => {
console.log(`onFulfilled ${res}`);
},
(err) => {
console.log(`onRejected ${err}`);
}
);
promise.then(
(res) => {
console.log(`onFulfilled 2`);
},
(err) => {
console.log(`onRejected 2`);
}
);
// 输出:
// onFulfilled 2
const MyPromise = require("./myPromise");
const promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
reject("失败");
});
});
promise.then(
(res) => {
console.log(`onFulfilled ${res}`);
},
(err) => {
console.log(`onRejected ${err}`);
}
);
promise.then(
(res) => {
console.log(`onFulfilled 2`);
},
(err) => {
console.log(`onRejected 2`);
}
);
// 输出:
// onFulfilled 2
可以发现,当任务为同步的时候,是可以按then
的调用顺序依次执行的,但是异步resolve
的时候,却不可以了。
- 原因在于:
- 当同步的时候,
promise
的状态已经是FULFILLED
了,当第二个then
任务的时候,会直接继续执行FULFILLED
状态的逻辑。 - 而异步
resolve/reject
的时候,由于之前使用的是onFulfilledCallback/onRejectedCallback
存储回调任务,但是由于使用的是单个变量,而第二个then
会覆盖第一个then
的回调函数,在第二次宏任务队列的时候,该回调函数才会被调用。
- 当同步的时候,
- 解决方法:
- 究其原因,就是
onCallback
的数据结构采用的不对,可以使用队列存储所有的回调函数,当resolve/reject
的时候,按顺序出队并且进行调用即可。
- 究其原因,就是
// MyPromise.js
// ...
class MyPromise {
// ...
// 存储成功/失败的回调函数
onFulfilledCallbackQueue = new Array();
onRejectedCallbackQueue = new Array();
resolve = (res) => {
// 如果成功且状态为PENDING
if (this.status === PENDING) {
this.status = FULFILLED;
this.res = res;
// 如果有成功的回调函数就执行
while (this.onFulfilledCallbackQueue.length > 0) {
this.onFulfilledCallbackQueue.shift()(res);
}
}
};
reject = (err) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.err = err;
// 如果有失败的回调函数就执行
while (this.onRejectedCallbackQueue.length > 0) {
this.onRejectedCallbackQueue.shift()(err);
}
}
};
then(onFulfilled, onRejected) {
if (this.status === FULFILLED) {
onFulfilled(this.res);
} else if (this.status === REJECTED) {
onRejected(this.err);
} else if (this.status === PENDING) {
this.onFulfilledCallbackQueue.push(onFulfilled);
this.onRejectedCallbackQueue.push(onRejected);
}
}
}
// 此时,输出可以按then的调用顺序执行
// MyPromise.js
// ...
class MyPromise {
// ...
// 存储成功/失败的回调函数
onFulfilledCallbackQueue = new Array();
onRejectedCallbackQueue = new Array();
resolve = (res) => {
// 如果成功且状态为PENDING
if (this.status === PENDING) {
this.status = FULFILLED;
this.res = res;
// 如果有成功的回调函数就执行
while (this.onFulfilledCallbackQueue.length > 0) {
this.onFulfilledCallbackQueue.shift()(res);
}
}
};
reject = (err) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.err = err;
// 如果有失败的回调函数就执行
while (this.onRejectedCallbackQueue.length > 0) {
this.onRejectedCallbackQueue.shift()(err);
}
}
};
then(onFulfilled, onRejected) {
if (this.status === FULFILLED) {
onFulfilled(this.res);
} else if (this.status === REJECTED) {
onRejected(this.err);
} else if (this.status === PENDING) {
this.onFulfilledCallbackQueue.push(onFulfilled);
this.onRejectedCallbackQueue.push(onRejected);
}
}
}
// 此时,输出可以按then的调用顺序执行
链式调用then
DANGER
Node
环境下输出结果有问题。
TIP
想要实现链式调用then
,就需要每次调用后,都返回一个含有then
方法的类
,在这里需要每次调用后返回一个MyPromise
对象,并且需要判断新对象的状态。
1. 可链式调用
// MyPromise.js
// ...
class MyPromise {
// ...
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
onFulfilled(this.res);
} else if (this.status === REJECTED) {
onRejected(this.err);
} else if (this.status === PENDING) {
this.onFulfilledCallbackQueue.push(onFulfilled);
this.onRejectedCallbackQueue.push(onRejected);
}
});
}
}
promise = new MyPromise((resolve, reject)=>{setTimeout(()=>{resolve(1);});});
promise.then((res)=>{console.log(res); return 2;}).then((res)=>{console.log(res);})
// 已经能够执行,但是没有调用第二个then的方法
// 输出:1
// MyPromise.js
// ...
class MyPromise {
// ...
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
onFulfilled(this.res);
} else if (this.status === REJECTED) {
onRejected(this.err);
} else if (this.status === PENDING) {
this.onFulfilledCallbackQueue.push(onFulfilled);
this.onRejectedCallbackQueue.push(onRejected);
}
});
}
}
promise = new MyPromise((resolve, reject)=>{setTimeout(()=>{resolve(1);});});
promise.then((res)=>{console.log(res); return 2;}).then((res)=>{console.log(res);})
// 已经能够执行,但是没有调用第二个then的方法
// 输出:1
2. 处理前一个then
的返回值(值为非Promise
)
// MyPromise.js
// ...
class MyPromise {
// ...
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
// 获取onFulfilled的返回值
const x = onFulfilled(this.res);
resolve(x);
} else if (this.status === REJECTED) {
onRejected(this.err);
} else if (this.status === PENDING) {
this.onFulfilledCallbackQueue.push(onFulfilled);
this.onRejectedCallbackQueue.push(onRejected);
}
});
}
}
promise = new MyPromise((resolve, reject)=>{setTimeout(()=>{resolve(1);});});
promise.then((res)=>{console.log(res); return 2;}).then((res)=>{console.log(res);})
// 输出:1 2
// MyPromise.js
// ...
class MyPromise {
// ...
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
// 获取onFulfilled的返回值
const x = onFulfilled(this.res);
resolve(x);
} else if (this.status === REJECTED) {
onRejected(this.err);
} else if (this.status === PENDING) {
this.onFulfilledCallbackQueue.push(onFulfilled);
this.onRejectedCallbackQueue.push(onRejected);
}
});
}
}
promise = new MyPromise((resolve, reject)=>{setTimeout(()=>{resolve(1);});});
promise.then((res)=>{console.log(res); return 2;}).then((res)=>{console.log(res);})
// 输出:1 2
3. 值为Promise
的情况
TIP
如果在 then
方法中返回一个新的 Promise
对象,那么下一个 then
方法会等待这个新的 Promise
对象完成,并且会将其结果作为参数传递给下一个 then
方法。
// MyPromise.js
// ...
class MyPromise {
// ...
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
const x = onFulfilled(this.res);
if(x instanceof MyPromise) {
// 如果x是MyPromise类,则等待x执行完后将结果作为下一个then的参数
x.then(resolve, reject);
} else {
resolve(x);
}
} else if (this.status === REJECTED) {
onRejected(this.err);
} else if (this.status === PENDING) {
this.onFulfilledCallbackQueue.push(onFulfilled);
this.onRejectedCallbackQueue.push(onRejected);
}
});
}
}
promise = new MyPromise((resolve, reject)=>{setTimeout(()=>{resolve(1);});});
promise.then((res)=>{console.log(res); return new MyPromise((resolve)=>{resolve(2);});}).then((res)=>{console.log(res);});
// 输出:1 2
// MyPromise.js
// ...
class MyPromise {
// ...
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
const x = onFulfilled(this.res);
if(x instanceof MyPromise) {
// 如果x是MyPromise类,则等待x执行完后将结果作为下一个then的参数
x.then(resolve, reject);
} else {
resolve(x);
}
} else if (this.status === REJECTED) {
onRejected(this.err);
} else if (this.status === PENDING) {
this.onFulfilledCallbackQueue.push(onFulfilled);
this.onRejectedCallbackQueue.push(onRejected);
}
});
}
}
promise = new MyPromise((resolve, reject)=>{setTimeout(()=>{resolve(1);});});
promise.then((res)=>{console.log(res); return new MyPromise((resolve)=>{resolve(2);});}).then((res)=>{console.log(res);});
// 输出:1 2
4. 返回值为本身
WARNING
在Promise
中,如果then
返回Promise
实例自身的话会报错。
const promise = new Promise((resolve)=>{resolve(1)});
const p1 = promise.then(()=>{return p1;});
// Uncaught (in promise) TypeError: Chaining cycle detected for promise #<Promise>
const promise = new Promise((resolve)=>{resolve(1)});
const p1 = promise.then(()=>{return p1;});
// Uncaught (in promise) TypeError: Chaining cycle detected for promise #<Promise>
在MyPromise
中,如果then
返回MyPromise
实例会怎么样呢?
const promise = new MyPromise((resolve)=>{resolve(1)});
const p1 = promise.then(()=>{return p1;});
// Uncaught ReferenceError: p1 is not defined
const promise = new MyPromise((resolve)=>{resolve(1)});
const p1 = promise.then(()=>{return p1;});
// Uncaught ReferenceError: p1 is not defined
为什么会出现p1 not defined
的情况呢,这是因为:在return p1
的时候,return new MyPromise
尚未执行成功,此时自然是没有p1
的。
在
return new MyPromise
后,再执行内部的方法可以将
then
内的逻辑变为一个微任务
,这个微任务
在return
后再执行,考虑使用queueMicrotask API
实现。js// MyPromise.js // ... class MyPromise { // ... then(onFulfilled, onRejected) { return new MyPromise((resolve, reject) => { if (this.status === FULFILLED) { queueMicrotask(() => { const x = onFulfilled(this.res); if (x instanceof MyPromise) { x.then(resolve, reject); } else { resolve(x); } }); } else if (this.status === REJECTED) { onRejected(this.err); } else if (this.status === PENDING) { this.onFulfilledCallbackQueue.push(onFulfilled); this.onRejectedCallbackQueue.push(onRejected); } }); } }
// MyPromise.js // ... class MyPromise { // ... then(onFulfilled, onRejected) { return new MyPromise((resolve, reject) => { if (this.status === FULFILLED) { queueMicrotask(() => { const x = onFulfilled(this.res); if (x instanceof MyPromise) { x.then(resolve, reject); } else { resolve(x); } }); } else if (this.status === REJECTED) { onRejected(this.err); } else if (this.status === PENDING) { this.onFulfilledCallbackQueue.push(onFulfilled); this.onRejectedCallbackQueue.push(onRejected); } }); } }
判断返回值是否为自身,如果是,则抛出错误
Type Error: ...
js// MyPromise.js // ... class MyPromise { // ... then(onFulfilled, onRejected) { const promise2 = new MyPromise((resolve, reject) => { if (this.status === FULFILLED) { queueMicrotask(() => { const x = onFulfilled(this.res); if (x === promise2) { return reject( new TypeError("Chaining cycle detected for promise #<Promise>") ); } if (x instanceof MyPromise) { x.then(resolve, reject); } else { resolve(x); } }); } else if (this.status === REJECTED) { onRejected(this.err); } else if (this.status === PENDING) { this.onFulfilledCallbackQueue.push(onFulfilled); this.onRejectedCallbackQueue.push(onRejected); } }); return promise2; } } const promise = new MyPromise((res)=>res(1)); const p1 = promise.then(()=>p1); p1.then(console.log,console.error); // TypeError: Chaining cycle detected for promise #<Promise>
// MyPromise.js // ... class MyPromise { // ... then(onFulfilled, onRejected) { const promise2 = new MyPromise((resolve, reject) => { if (this.status === FULFILLED) { queueMicrotask(() => { const x = onFulfilled(this.res); if (x === promise2) { return reject( new TypeError("Chaining cycle detected for promise #<Promise>") ); } if (x instanceof MyPromise) { x.then(resolve, reject); } else { resolve(x); } }); } else if (this.status === REJECTED) { onRejected(this.err); } else if (this.status === PENDING) { this.onFulfilledCallbackQueue.push(onFulfilled); this.onRejectedCallbackQueue.push(onRejected); } }); return promise2; } } const promise = new MyPromise((res)=>res(1)); const p1 = promise.then(()=>p1); p1.then(console.log,console.error); // TypeError: Chaining cycle detected for promise #<Promise>
捕获报错转为rejected
状态
1. 执行器有错误捕获
// MyPromise.js
class MyPromise {
constructor(executor) {
try {
executor(this.resolve, this.reject);
} catch (err) {
this.reject(err);
}
}
}
const promise = new MyPromise((resolve, reject) => {
throw new Error('a new error!');
});
promise.then(console.log,console.error); // Error: a new error!
// MyPromise.js
class MyPromise {
constructor(executor) {
try {
executor(this.resolve, this.reject);
} catch (err) {
this.reject(err);
}
}
}
const promise = new MyPromise((resolve, reject) => {
throw new Error('a new error!');
});
promise.then(console.log,console.error); // Error: a new error!
2. then
执行有错误并捕获
// MyPromise.js
// ...
class MyPromise {
// ...
then(onFulfilled, onRejected) {
const promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
queueMicrotask(() => {
try{
const x = onFulfilled(this.res);
if (x === promise2) {
return reject(
new TypeError("Chaining cycle detected for promise #<Promise>")
);
}
if (x instanceof MyPromise) {
x.then(resolve, reject);
} else {
resolve(x);
}
} catch (err) {
reject(err);
}
});
} else if (this.status === REJECTED) {
onRejected(this.err);
} else if (this.status === PENDING) {
this.onFulfilledCallbackQueue.push(onFulfilled);
this.onRejectedCallbackQueue.push(onRejected);
}
});
return promise2;
}
}
const promise = new MyPromise((res, rej)=>res(1));
promise.then((res)=>{console.log(res);throw new Error('another new error!')}).then(console.log, console.error);
// 1
// TypeError: Chaining cycle detected for promise #<Promise>
// MyPromise.js
// ...
class MyPromise {
// ...
then(onFulfilled, onRejected) {
const promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
queueMicrotask(() => {
try{
const x = onFulfilled(this.res);
if (x === promise2) {
return reject(
new TypeError("Chaining cycle detected for promise #<Promise>")
);
}
if (x instanceof MyPromise) {
x.then(resolve, reject);
} else {
resolve(x);
}
} catch (err) {
reject(err);
}
});
} else if (this.status === REJECTED) {
onRejected(this.err);
} else if (this.status === PENDING) {
this.onFulfilledCallbackQueue.push(onFulfilled);
this.onRejectedCallbackQueue.push(onRejected);
}
});
return promise2;
}
}
const promise = new MyPromise((res, rej)=>res(1));
promise.then((res)=>{console.log(res);throw new Error('another new error!')}).then(console.log, console.error);
// 1
// TypeError: Chaining cycle detected for promise #<Promise>
参数onFulfilled/onRejected
可选
TIP
为onFulfilled/onRejected
添加默认值即可。
onFulfilled
不存在,那么默认为将已有结果返回给下一个then
onRejected
不存在,那么默认为将已有的错误继续抛出给下一个then
// MyPromise.js
// ...
class MyPromise {
// ...
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : res => res;
onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err; };
const promise2 = new MyPromise((resolve, reject) => {
// ...
}
}
}
const promise = new MyPromise((res, rej)=>res(1));
const promise2 = new MyPromise((res,rej)=>{ throw new Error('3rd error!'); });
promise.then().then((res)=>{console.log(res);}); // 1
promise2.then().then(console.log, console.error); // Error: 3rd error!
// MyPromise.js
// ...
class MyPromise {
// ...
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : res => res;
onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err; };
const promise2 = new MyPromise((resolve, reject) => {
// ...
}
}
}
const promise = new MyPromise((res, rej)=>res(1));
const promise2 = new MyPromise((res,rej)=>{ throw new Error('3rd error!'); });
promise.then().then((res)=>{console.log(res);}); // 1
promise2.then().then(console.log, console.error); // Error: 3rd error!
实现Promise.resolve()/Promise.reject()
静态方法
// MyPromise.js
// ...
class MyPromise {
// ...
static resolve(value) {
if(value instanceof MyPromise) {
return value;
} else {
return new MyPromise((resolve) => {
resolve(value);
})
}
}
static reject(err) {
return new MyPromise((_resolve, reject) => {
reject(err);
})
}
}
MyPromise.resolve(1); // MyPromise {res: 1, status: 'fulfilled', ...}
MyPromise.resolve(new MyPromise((resolve)=>{resolve(2);})); // MyPromise {res: 2, status: 'fulfilled', ...}
MyPromise.reject(new Error(3)); // MyPromise {err: 3, status: 'rejected', ...}
// MyPromise.js
// ...
class MyPromise {
// ...
static resolve(value) {
if(value instanceof MyPromise) {
return value;
} else {
return new MyPromise((resolve) => {
resolve(value);
})
}
}
static reject(err) {
return new MyPromise((_resolve, reject) => {
reject(err);
})
}
}
MyPromise.resolve(1); // MyPromise {res: 1, status: 'fulfilled', ...}
MyPromise.resolve(new MyPromise((resolve)=>{resolve(2);})); // MyPromise {res: 2, status: 'fulfilled', ...}
MyPromise.reject(new Error(3)); // MyPromise {err: 3, status: 'rejected', ...}
完整代码
// MyPromise.js
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(executor) {
try {
executor(this.resolve, this.reject);
} catch (err) {
this.reject(err);
}
}
static resolve(value) {
if (value instanceof MyPromise) {
return value;
} else {
return new MyPromise((resolve) => {
resolve(value);
});
}
}
static reject(err) {
return new MyPromise((_resolve, reject) => {
reject(err);
});
}
// 存储成功的参数
res = null;
// 存储失败的参数
err = null;
// 初始状态
status = PENDING;
// 存储成功/失败的回调函数
onFulfilledCallbackQueue = new Array();
onRejectedCallbackQueue = new Array();
resolve = (res) => {
// 如果成功且状态为PENDING
if (this.status === PENDING) {
this.status = FULFILLED;
this.res = res;
// 如果有成功的回调函数就执行
while (this.onFulfilledCallbackQueue.length > 0) {
this.onFulfilledCallbackQueue.shift()(res);
}
}
};
reject = (err) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.err = err;
// 如果有失败的回调函数就执行
while (this.onRejectedCallbackQueue.length > 0) {
this.onRejectedCallbackQueue.shift()(err);
}
}
};
then(onFulfilled, onRejected) {
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (res) => res;
onRejected =
typeof onRejected === "function"
? onRejected
: (err) => {
throw err;
};
const promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
queueMicrotask(() => {
try {
const x = onFulfilled(this.res);
if (x === promise2) {
return reject(
new TypeError("Chaining cycle detected for promise #<Promise>")
);
}
if (x instanceof MyPromise) {
x.then(resolve, reject);
} else {
resolve(x);
}
} catch (err) {
reject(err);
}
});
} else if (this.status === REJECTED) {
onRejected(this.err);
} else if (this.status === PENDING) {
this.onFulfilledCallbackQueue.push(onFulfilled);
this.onRejectedCallbackQueue.push(onRejected);
}
});
return promise2;
}
}
if (typeof module !== "undefined" && module.exports) {
// 在 Node.js 环境中
module.exports = MyPromise;
}
// MyPromise.js
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(executor) {
try {
executor(this.resolve, this.reject);
} catch (err) {
this.reject(err);
}
}
static resolve(value) {
if (value instanceof MyPromise) {
return value;
} else {
return new MyPromise((resolve) => {
resolve(value);
});
}
}
static reject(err) {
return new MyPromise((_resolve, reject) => {
reject(err);
});
}
// 存储成功的参数
res = null;
// 存储失败的参数
err = null;
// 初始状态
status = PENDING;
// 存储成功/失败的回调函数
onFulfilledCallbackQueue = new Array();
onRejectedCallbackQueue = new Array();
resolve = (res) => {
// 如果成功且状态为PENDING
if (this.status === PENDING) {
this.status = FULFILLED;
this.res = res;
// 如果有成功的回调函数就执行
while (this.onFulfilledCallbackQueue.length > 0) {
this.onFulfilledCallbackQueue.shift()(res);
}
}
};
reject = (err) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.err = err;
// 如果有失败的回调函数就执行
while (this.onRejectedCallbackQueue.length > 0) {
this.onRejectedCallbackQueue.shift()(err);
}
}
};
then(onFulfilled, onRejected) {
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (res) => res;
onRejected =
typeof onRejected === "function"
? onRejected
: (err) => {
throw err;
};
const promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
queueMicrotask(() => {
try {
const x = onFulfilled(this.res);
if (x === promise2) {
return reject(
new TypeError("Chaining cycle detected for promise #<Promise>")
);
}
if (x instanceof MyPromise) {
x.then(resolve, reject);
} else {
resolve(x);
}
} catch (err) {
reject(err);
}
});
} else if (this.status === REJECTED) {
onRejected(this.err);
} else if (this.status === PENDING) {
this.onFulfilledCallbackQueue.push(onFulfilled);
this.onRejectedCallbackQueue.push(onRejected);
}
});
return promise2;
}
}
if (typeof module !== "undefined" && module.exports) {
// 在 Node.js 环境中
module.exports = MyPromise;
}