手写Promise
构造器的实现
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'
class MyPromise{
#state = PENDING;
#result = undefined;
constructor(executor){
const resolve = (data) => {
this.#changeState(FULFILLED, data);
};
const reject = (reason) => {
this.#changeState(REJECTED, reason);
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
#changeState(state, result){
if(this.#state !== PENDING) return;
this.#state = state;
this.#result = result;
}
}
const p = new MyPromise((resolve, reject) =>{
resolve(1);
});
- Promise 的状态一旦定下来之后,在后续的所有过程中都不可能再去改变它的状态了
- 如果再执行过程中报错,会执行rejected,但是捕获不到异步错误
Promise-then的回调执行时机
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'
class MyPromise{
#state = PENDING;
#result = undefined;
#handlers = [];
constructor(executor){
const resolve = (data) => {
this.#changeState(FULFILLED, data);
};
const reject = (reason) => {
this.#changeState(REJECTED, reason);
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
#changeState(state, result){
if(this.#state !== PENDING) return;
this.#state = state;
this.#result = result;
this.#run();
}
#run(){
if(this.#state === PENDING) return;
while(this.#handlers.length){
const {onFulfilled, onRejected, resolve, reject} = this.#handlers.shift();
if(this.#state === FULFILLED){
if(typeof onFulfilled === 'function'){
onFulfilled(this.#result)
}
}
else{
if(typeof onRejected === 'function'){
onRejected(this.#result)
}
}
}
}
then(onFulfilled, onRejected){
return new MyPromise((resolve, reject) =>{
this.#handlers.push({
onFulfilled,
onRejected,
resolve,
reject,
});
this.#run();
});
}
}
const p = new MyPromise((resolve, reject) =>{
setTimeout(()=>{
resolve(123);
},1000)
});
p.then(
(res) =>{
console.log('promise 成功1', res);
},
(err) =>{
console.log('promise 失败1', err);
}
);
p.then(
(res) =>{
console.log('promise 成功2', res);
},
(err) =>{
console.log('promise 失败2', err);
}
);
p.then(
(res) =>{
console.log('promise 成功3', res);
},
(err) =>{
console.log('promise 失败3', err);
}
);
为了判断什么时候调用,所以用一个handlers数组记录,并用run函数调用
Promise-then 的返回值
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'
class MyPromise{
#state = PENDING;
#result = undefined;
#handlers = [];
constructor(executor){
const resolve = (data) => {
this.#changeState(FULFILLED, data);
};
const reject = (reason) => {
this.#changeState(REJECTED, reason);
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
#changeState(state, result){
if(this.#state !== PENDING) return;
this.#state = state;
this.#result = result;
this.#run();
}
// 判断一个函数是不是Promise(是否满足A+规范)
#isPromiseLike(value){
return value && typeof value.then === 'function' && (typeof value === 'object' || typeof value === 'function');
}
// 把一个函数放到微队列
#runMicroTask(func){
// node nextTick
if(process && process.nextTick){
process.nextTick(func);
}
// 浏览器 MutationObserver
else if(typeof MutationObserver === 'function'){
const ob = new MutationObserver(fn);
const text = document.createTextNode('1');
ob.observe(text, { characterData: true});
text.data = '2';
}
else{
setTimeout(fn, 0);
}
}
#runOne(callback, resolve, reject){
this.#runMicroTask(()=>{
if(typeof callback !== 'function'){
const settled = this.#state === FULFILLED ? resolve : reject;
settled(this.#result);
return;
}
try {
const data = callback(this.#result);
if(this.#isPromiseLike(data)){
data.then(resolve, reject);
}else{
resolve(data);
}
} catch (err) {
reject(err);
}
});
}
#run(){
if(this.#state === PENDING) return;
while(this.#handlers.length){
const {onFulfilled, onRejected, resolve, reject} = this.#handlers.shift();
if(this.#state === FULFILLED){
this.#runOne(onFulfilled, resolve, reject);
}
else{
this.#runOne(onRejected, resolve, reject);
}
}
}
then(onFulfilled, onRejected){
return new MyPromise((resolve, reject) =>{
this.#handlers.push({
onFulfilled,
onRejected,
resolve,
reject,
});
this.#run();
});
}
}
const p = new MyPromise((resolve, reject) =>{
setTimeout(()=>{
reject(123);
},1000)
});
p.then(
null,
(err) =>{
console.log('promise 失败', err);
return 456;
}
).then((data) =>{
console.log("ok",data);
});
这里有三种情况:
- 对应的回调不是函数的情况
- 回调是一个函数的情况
- 返回结果是一个Promise的情况