个人简介:
大家好,我是polar,一个 前端攻城狮/动漫爱好者/科技控/AI观察家/95%的素食主义者/,欢迎大家来找我扩列,一起愉快玩耍。
从今天起,我会开始更新一个系列【polar的复习笔记】,用于总结梳理相关的知识点,构建前端知识图谱,也同时欢迎大家一起来探讨交流。
下面一起来复习一下promise:
promise的特点
- promise 是一个构造函数,默认需要传入一个executor执行器
- executor会立刻执行,并传入 resolve 和 reject 两个参数
- promise 有三种状态 fulfilled 成功 reject 拒绝态 pending 等待态
- 每个promise都有一个then方法,可以访问到成功或者失败的原因
- 可以通过resolve和reject来改变状态,同时调用对应的回调
- 当executor 发生异常的时候,也会触发promise的失败
promise then链的特点
- then链的特点,当then中成功和失败的回调函数返回的是一个promise,内部会解析这个promise,并将结果传递到外层的下一个then
- 下一次then走成功还是失败,取决于当前的promise状态
- 如果then返回的不是一个promise,那么这个结果会直接传递到下一个then的成功
- 如果then的回调中抛异常了,那么会执行下一个then的失败
一个完整符合promiseA+规范的promise实现如下:
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
// 为了所有then的promise都可以相互调用,所以所有的promise都要遵循这个规则
function resolvePromise (promise2, x, resolve, reject) {
// 这个方法会处理的严谨一些,保证所有人的promise可以相互调用
// 自己等自己会循环卡死
if (x === promise2) {
return reject(TypeError('cycle error'));
}
// 判断是不是promise
if ((typeof x === 'object' && x) || (typeof x === 'function')) {
let called = false;
// 有可能是promise
// 之所以catch,是因为可能有代理(defineProperty)
try {
let then = x.then;
if (typeof then === 'function') {
// 是promise
then.call(x, (y)=> {
if (called) return;
called = true;
// resolve(y);
// 排除y还是promise的情况,使用resolvePromise递归解析
resolvePromise (promise2, y, resolve, reject)
}, (r)=>{
if (called) return;
called = true;
reject(r);
});
} else {
if (called) return;
called = true;
// 是对象或者函数
resolve(x);
}
} catch (e) {
reject(e);
}
} else {
resolve(x); // 普通值,直接将结果传递到下面
}
}
class Promise {
constructor (executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
// promise 调用 this的时候,状态可能依旧是 pending,那么我们需要先将回调存放起来
// 等resolve触发的时候,onResolvedCallbacks 执行
// 调用reject的时候,onRejectedCallbacks 执行
const resolve = (value) => {
if (this.status === PENDING) {
// 只有状态是pending的时候,才能修改状态和 改变是成功和失败的原因
this.status = FULFILLED;
this.value = value;
this.onResolvedCallbacks.forEach(item => {
item();
})
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach(item => {
item();
})
}
}
// 调用executor 会自动传入 resolve 和 reject
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then (onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v=>v;
onRejected = typeof onRejected === 'function' ? onRejected : e=>{throw e};
let promise2 = new Promise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
if (this.status === PENDING) {
// this.onResolvedCallbacks.push(onFulfilled);
// this.onRejectedCallbacks.push(onRejected);
// 为了在调用函数之前做些处理,使用一个函数将其包起来
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
})
}
})
return promise2;
}
}
module.exports = Promise;