1、Promise的声明
(1)promise接收一个函数(executor)并且立即执行
(2)executor有两个参数,resolve(成功)和reject(失败)
class MyPromise {
//构造器
constructor(executor) {
//成功
let resolve = () => {};
//失败
let reject = () => {};
//立即执行
executor(resolve,reject)
}
}
2、解决基本状态
(1)Promise有三个状态(state),初始态(pending),成功态(fulfilled),失败态(rejected)
(2) pending(等待态)为初始态,并可以转化为fulfilled(成功态)和rejected(失败态)
(3)成功时,不可转为其他状态,且必须有一个不可改变的值(value)
(4)失败时,不可转为其他状态,且必须有一个不可改变的原因(reason)
(5) new Promise((resolve, reject)=>{resolve(value)}) resolve为成功,接收参数value,状态改变为fulfilled,不可再次改变
(6) new Promise((resolve, reject)=>{reject(reason)}) reject为失败,接收参数reason,状态改变为rejected,不可再次改变。
(7)若是executor函数报错 直接执行reject();
class Promise{
constructor(executor){
// 初始化state为等待态
this.state = 'pending';
// 成功的值
this.value = undefined;
// 失败的原因
this.reason = undefined;
let resolve = value => {
// state改变,resolve调用就会失败
if (this.state === 'pending') {
// resolve调用后,state转化为成功态
this.state = 'fulfilled';
// 储存成功的值
this.value = value;
}
};
let reject = reason => {
// state改变,reject调用就会失败
if (this.state === 'pending') {
// reject调用后,state转化为失败态
this.state = 'rejected';
// 储存失败的原因
this.reason = reason;
}
};
// 如果executor执行报错,直接执行reject
try{
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
}
3、then方法
Promise有一个叫做then的方法,里面有两个参数:onFulfilled,onRejected,成功有成功的值,失败有失败的原因
(1)当状态state为fulfilled,则执行onFulfilled,传入this.value。当状态state为rejected,则执行onRejected,传入this.value
(2)onFulfilled,onRejected如果他们是函数,则必须分别在fulfilled,rejected后被调用,value或reason依次作为他们的第一个参数
class Promise{
constructor(executor){...}
// then 方法 有两个参数onFulfilled onRejected
then(onFulfilled,onRejected) {
// 状态为fulfilled,执行onFulfilled,传入成功的值
if (this.state === 'fulfilled') {
onFulfilled(this.value);
};
// 状态为rejected,执行onRejected,传入失败的原因
if (this.state === 'rejected') {
onRejected(this.reason);
};
}
}
4、解决异步实现
现在基本可以实现简单的同步代码,但是当resolve在setTomeout内执行,then执行时state还是pending等待状态 我们就需要在then调用的时候,将成功和失败存到各自的数组,一旦reject或者resolve,就调用它们
类似于发布订阅,先将then里面的两个函数储存起来,由于一个promise可以有多个then,所以存在同一个数组内,成功或者失败时,forEach调用它们
class Promise{
constructor(executor){
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
// 成功存放的数组
this.onResolvedCallbacks = [];
// 失败存放法数组
this.onRejectedCallbacks = [];
let resolve = value => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
// 一旦resolve执行,调用成功数组的函数
this.onResolvedCallbacks.forEach(fn=>fn());
}
};
let reject = reason => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
// 一旦reject执行,调用失败数组的函数
this.onRejectedCallbacks.forEach(fn=>fn());
}
};
try{
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled,onRejected) {
if (this.state === 'fulfilled') {
onFulfilled(this.value);
};
if (this.state === 'rejected') {
onRejected(this.reason);
};
// 当状态state为pending时
if (this.state === 'pending') {
// onFulfilled传入到成功数组
this.onResolvedCallbacks.push(()=>{
onFulfilled(this.value);
})
// onRejected传入到失败数组
this.onRejectedCallbacks.push(()=>{
onRejected(this.value);
})
}
}
}
5、解决链式调用
我门常常用到 new Promise().then().then() ,这就是链式调用,用来解决回调地狱
(1)为了达成链式,我们默认在第一个then里返回一个promise。所以我们需要在then里面返回一个新的promise,称为promise2: promise2 = new Promise((resolve, reject)=>{})
• 将这个promise2返回的值传递到下一个then中
• 如果返回一个普通的值,则将普通的值传递给下一个then中
(2)当我们在第一个then中 return 了一个参数(参数未知,需判断)。这个return出来的新的promise就是onFulfilled()或onRejected()的值
onFulfilled()或onRejected()的值,即第一个then返回的值,叫做x,判断x的函数叫做resolvePromise
class Promise{
constructor(executor){
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
let resolve = value => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onResolvedCallbacks.forEach(fn=>fn());
}
};
let reject = reason => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn=>fn());
}
};
try{
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled,onRejected) {
// 声明返回的promise2
let promise2 = new Promise((resolve, reject)=>{
if (this.state === 'fulfilled') {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
};
if (this.state === 'rejected') {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
};
if (this.state === 'pending') {
this.onResolvedCallbacks.push(()=>{
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
})
this.onRejectedCallbacks.push(()=>{
let x = onRejected(this.value);
resolvePromise(promise2, x, resolve, reject);
})
}
});
// 返回promise,完成链式
return promise2;
}
}
(3)resolvePromise函数
function resolvePromise(promise2, x, resolve, reject) {
//如果 promise2 和 x 相等,意味着你试图将同一个 promise 作为自己的接下来的状态,这时会产生 “循环引用” 错误。为了防止无限循环,需要通过调用 reject 来拒绝 promise2,并给出 TypeError 作为原因。
if (promise2 === x) {
return reject(new TypeError("Chaining cycle detected for promise"));
}
// 如果 x 是一个 thenable 对象,即它具有 then 方法,这可能是你的 MyPromise 实例或者任何符合 Promises/A+ 规范的 promise 实现。这时,你需要“接续”这个 promise:调用它的 then 方法,并将 resolve 和 reject 函数传递进去。这样 x 的状态就会被传递给 promise2。
if (x instanceof MyPromise) {
//instanceof检查一个对象(x)是否是特定构造函数(MyPromise)创建的对象
//或者理解为 测试一个对象是否是一个类或者构造函数的原型链中的实例
x.then(resolve, reject);
} else {
// 如果 x 不是一个 thenable 对象,那么它可能是一个普通值。在这种情况下,可以直接使用 resolve 方法解决 promise2 并传递 x 作为值。
reject(x);
}
}
6、其他问题
(1)onFulfilled,onRejected都是可选参数,如果他们不是函数,必须被忽略
• onFulfilled返回一个普通的值,成功时直接等于 value => value
• onRejected返回一个普通的值,失败时如果直接等于 value => value,则会跑到下一个then中的onFulfilled中,所以直接扔出一个错误 reason => throw err
(2)onFulfilled或onRejected不能同步被调用,必须异步调用。我们就用setTimeout解决异步问题
• 如果onFulfilled或onRejected报错,则直接返回reject()
class Promise{
constructor(executor){
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
let resolve = value => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onResolvedCallbacks.forEach(fn=>fn());
}
};
let reject = reason => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn=>fn());
}
};
try{
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled,onRejected) {
// onFulfilled如果不是函数,就忽略onFulfilled,直接返回value
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
// onRejected如果不是函数,就忽略onRejected,直接扔出错误
onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };
let promise2 = new Promise((resolve, reject) => {
if (this.state === 'fulfilled') {
// 异步
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
};
if (this.state === 'rejected') {
// 异步
setTimeout(() => {
// 如果报错
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
};
if (this.state === 'pending') {
this.onResolvedCallbacks.push(() => {
// 异步
setTimeout(() => {
try {
let x = onFulfilled(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)
});
};
});
// 返回promise,完成链式
return promise2;
}
}
7、catch,race,all,finally方法
catch(onRejected) {
return this.then(undefined, onRejected);
}
//取最快执行的结果
race(promises) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(resolve, reject);
}
});
}
//全部执行完毕
all(promises) {
let arr = [];
let i = 0;
const processData = (index, value) => {
arr[index] = value;
i++;
if (promises.length === i) {
resolve(arr);
}
};
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then((data) => {
processData(index, data);
}, reject);
}
});
}
// finally方法 不管成功失败都会执行一次
finally(callback) {
return this.then(
(value) => {
return MyPromise.resolve(callback()).then(() => value);
},
(reason) => {
return MyPromise.reject(callback()).then(() => {
throw reason;
});
}
);
}