一、Promise使用
1、没有Promise之前的处理
// 以前是使用回调函数
// 这种回调的方式有很多的弊端:
// 1> 如果是我们自己缝制的requestData,那么我们在封装的时候必须自己设计好callback名称
// 2> 如果是别人封装的,那我们必须去看别人的源码,看参数等,才能获取到结果
// request.js
function requestData(url, successCallback, errorCallback) {
// 模拟网络请求
setTimeout(() => {
// 拿到请求的结果
// url传入的是chen, 请求成功
if (url === "chen") {
// 成功
let names = ["a", "b", "c", "d", "e", "f"];
successCallback(names);
} else {
// 失败
let errMessage = "请求失败";
failCallback(errMessage);
}
}, 3000);
}
requestData(
"chen",
() => {
console.log("成功他妈");
},
() => {
console.log("失败他爹");
}
);
2、promise的基本使用
class Person {
constructor(callback) {
let foo = function () {};
let bar = function () {};
callback(foo, bar);
}
}
// const p = new Person("chen", 23);
const p = new Person((foo, bar) => {
console.log("hello");
// 这两个foo, bar又是函数,本身是可以执行的
});
// promise需要传入一个回调函数() => {}, 传入的这个函数会立即执行, 这个函数叫executor
const promise = new Promise((resolve, reject) => {
console.log("promise传入的参数被执行了");
// 本身是可以执行的
resolve(); // resolve(), 来到promise.then(() =>{})
// reject(); 如果是调用reject(), 它会来到promise.catch(()=>{})
});
// then方法传入的函数,会在promise执行resolve函数是被回调。
promise.then(() => {});
3、异步请求的promise改造
// request.js
function requestData(url) {
// 异步请求的代码会被放入到executor中
return new Promise((resolve, reject) => {
setTimeout(() => {
if (url === "chen") {
let names = ["a", "b", "c"];
resolve(names);
} else {
// 失败
let errMessage = "请求失败";
reject(errMessage);
}
}, 3000);
});
}
// requestData(
// "chen",
// () => {
// console.log("成功他妈");
// },
// () => {
// console.log("失败他爹");
// }
// );
const promise = requestData("chen");
promise.then((res) => {
console.log("成功 " + res);
});
promise.catch(() => {
console.log("失败");
});
// 开发中一般直接写成这样
promise
.then(() => {
console.log("成功");
})
.catch(() => {
console.log("失败");
});
// 其实then里面也是可以放两个函数的, 第一是成功的回调,第二个是执行reject是的回调
promise.then(
(res) => {
console.log('成功');
},
(err) => {}
);
4、promise的resolve详解
// const promise = new Promise((resolve, reject) => {});
// promise.then(
// (res) => {},
// (err) => {}
// );
// 完全等价于下面的写法
// 给promise划分状态: pedding
// Promise状态一旦确定下来,那么就是不可更改的(锁定)
new Promise((resolve, reject) => {
console.log("----------------直接执行"); // promise处于pedding状态
resolve(res);
reject(res); //这行代码是没有意义的,已经锁定了
})
.then((res) => {
// fulfiled状态(已固定)
console.log("res成功");
})
.catch((err) => {
// rejected状态(已拒绝)
console.log("res失败");
});
5、Promise的resolve参数
/**
* resolve(参数)
* 1> 普通的值或者对象 pedding -> fulfiled
* 2> 传入一个Promise, 那么当前的Promise的状态会有传入的Promise来决定
* 相当于状态进行移交
*
* 3> 传入一个对象,并且这个对象有实现then方法,那么也会执行该then方法,并且有该then方法决定后续状态
*/
// 2.传入一个Promise
// new Promise((resolve, reject) => {
// // resolve({ name: "chen" }); //普通的对象
// resolve(
// new Promise((resolve, reject) => {
// // 当传入的是Promise的时候,需要先调用这个promise
// // resolve('aaaa'); //来到下面then中的res
// reject("bbb"); //来到下面then中的err
// })
// );
// }).then(
// (res) => {
// console.log("res===", res);
// },
// (err) => {
// console.log("err", err);
// }
// );
// 3.传入一个对象
new Promise((resolve, reject) => {
const obj = {
then(resolve, reject) {
resolve("resolve message");
},
};
resolve(obj);
}).then(
(res) => {
console.log("res===", res);
},
(err) => {
console.log("err", err);
}
);
6、Promise中的then方法(重要)
// Promise有哪些对象方法
// console.log(Object.getOwnPropertyDescriptors(Promise.prototype));
const promise = new Promise(function (resolve, reject) {
resolve("hahahha");
});
// 1.同一个Promise可以被多次调用then方法
// 当我们的resolveb被回调是,所有的then方法都会被回调
promise.then((res) => {
console.log("res1===", res);
});
promise.then((res) => {
console.log("res2===", res);
});
// 2.then方法传入的'回调函数'是可以有返回值的
// then方法本身也是有返回值的,他的返回值是Promise
// 1> 如果我们返回的是一个普通的值(数值/字符串/普通对象/undefined),那么这个普通的值会被当成Promise中的resolve值
// 链式调用
promise
.then((res) => {
// 相当于new Promise((resolve, reject) =>{ resolve(111)})
return 111; //这个值会被包裹成Promise。如果没有写返回值,返回的是undefined;
})
.then((res) => {
console.log("res1---", res); //res1--- 111
return "aaaa";
})
.then((res) => {
console.log("res2===", res); //res2=== aaaa
});
// 2> 如果返回的是一个Promise,依然会继续使用new Promise()进行包裹
promise
.then((res) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1111);
}, 4000);
});
})
.then((res) => {
console.log(
"这里也是会被延迟3秒的,由then里面return 传入的promise状态决定外面的promise状态",
res
);
});
// 3> 如果返回的是一个对象,并且该对象实现了thenable,那么下一次.then(res)中的res,是由对象中的then决定的
promise
.then((res) => {
return {
then: function (resolve, reject) {
resolve(2222);
},
};
})
.then((res) => {
console.log("对象中的then决定", res);
});
7、Promise中的catch方法
const promise = new Promise((resolve, reject) => {
reject("Error");
// 其实抛出异常,也会执行第二个回调
// throw new Error("reject error");
});
// 1、当executor抛出异常时,也是会调用错误捕获的回调函数的
promise.then(
() => {},
(err) => {
console.log("err----", err);
}
);
// 2、通过catch方法传入错误捕获的回调函数,只是另外一种写法
// promise/a+规范
promise.catch((err) => {
console.log("err===", err);
});
// 3、es6中的语法糖
promise
.then((res) => {
return 4444;
})
.catch((err) => {
console.log("es6红=====", err);
});
// 4、catch方法的返回值.catch 返回值也是会被包裹成promise
const promise1 = new Promise((resolve, reject) => {
reject("2222");
});
promise1
.then((res) => {
console.log("res====", res);
})
.catch((err) => {
console.log("err:", err);
return "catch return value";
})
.then((res) => {
console.log("res result===", res);
})
.catch((err) => {
console.log("err result===", err);
});
8、Promise类方法 - resolve
// 类方法Promise.resolve:
// 将一个对象转成Promise
// 1.传入一个普通的值
const promise = Promise.resolve({
name: "chen",
});
// 上面的写法,相当于下面
// const promise2 = new Promise((resolve, reject) => {
// resolve({ name: "zhoaliu" });
// });
promise.then((res) => {
console.log("res", res);
});
// 2.传入Promise
const promise3 = Promise.resolve(
new Promise((resolve, reject) => {
resolve(99999999);
})
);
promise3.then((res) => {
console.log("res===", res);
});
9、Promise类方法 - reject
const promise = Promise.reject("reject message");
// 相当于
// const promise2 = new Promise((resolve, reject) => {
// reject("reject message");
// });
// reject不管传入什么值,都是一样的,
promise
.then((res) => {
console.log("res", res);
})
.catch((err) => {
console.log("err===", err);
});
11、Promise类方法 - all
// 创建多个promise
const p1 = new Promise((resolve, reject) => {
resolve(111);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(222);
}, 2020);
});
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(222);
// resolve("222");
}, 3000);
});
// 需求:3个都有结果在调用后面的函数。当然,也可以放’aaa‘
// all也是返回一个Promise
// 意外:如果我们在拿到所有结果之前,有一个Promise变成了rejected, 那么整个Promise是rejected
Promise.all([p1, p2, p3, "aaa"])
.then((res) => {
console.log(res);
// 返回的是一个数组,是按照数组中的顺序返回的
})
.catch((err) => {
console.log(err);
});
12、Promise类方法 - allSettled
const p1 = new Promise((resolve, reject) => {
resolve(111);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(222);
}, 2020);
});
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(222); //allSettled是不会来到catch里面的
}, 3000);
});
Promise.allSettled([p1, p2, p3, "aaa"])
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
13、Promise类方法 - race
const p1 = new Promise((resolve, reject) => {
resolve(111);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(222);
}, 2020);
});
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(222); //allSettled是不会来到catch里面的
}, 3000);
});
// 只要有一个变成fulfilled, 那么就结束。
Promise.race([p1, p2, p3, "aaa"])
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
14、Promise类方法 - any
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(111);
}, 1000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(222);
}, 2020);
});
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(333);
}, 500);
});
Promise.any([p1, p2, p3])
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
二、手写Promise
1、手写Promise-结构的设计
// 1.状态的设计
const PROMISE_STATE_PENDING = "pending";
const PROMISE_STATE_FULFILED = "fulfiled";
const PROMISE_STATE_REJECTED = "rejected";
class MyPromise {
constructor(executor) {
this.status = PROMISE_STATE_PENDING;
this.value = null;
this.reason = null;
const resolve = (value) => {
if (this.status === PROMISE_STATE_PENDING) {
this.status = PROMISE_STATE_FULFILED;
this.value = value;
console.log("resolve被调用了");
}
};
const reject = (reason) => {
if (this.status === PROMISE_STATE_PENDING) {
this.status = PROMISE_STATE_REJECTED;
}
console.log("reject被调用了");
};
executor(resolve, reject);
}
}
const promise = new MyPromise((resolve, reject) => {
console.log("传入的函数直接被调用了 pending===");
reject(111);
resolve(222);
});
// 当我们调用then的时候,应该需要两个变量来保存
promise.then(
(res) => {},
(err) => {}
);
2、手写Promise-then方法的设计
// 1.状态的设计
const PROMISE_STATE_PENDING = "pending";
const PROMISE_STATE_FULFILED = "fulfiled";
const PROMISE_STATE_REJECTED = "rejected";
class MyPromise {
constructor(executor) {
this.status = PROMISE_STATE_PENDING;
this.value = null;
this.reason = null;
const resolve = (value) => {
if (this.status === PROMISE_STATE_PENDING) {
this.status = PROMISE_STATE_FULFILED;
queueMicrotask(() => {
this.value = value;
console.log("resolve被调用了");
// 我们需要执行then传进来的第一个函数
this.onfulfilled(this.value);
});
}
};
const reject = (reason) => {
if (this.status === PROMISE_STATE_PENDING) {
this.status = PROMISE_STATE_REJECTED;
queueMicrotask(() => {
this.reason = reason;
console.log("reject被调用了");
// 我们需要执行then传进来的第二个函数
this.onrejected(this.reason);
});
}
};
executor(resolve, reject);
}
then(onfulfilled, onrejected) {
this.onfulfilled = onfulfilled;
this.onrejected = onrejected;
}
}
const promise = new MyPromise((resolve, reject) => {
console.log("传入的函数直接被调用了 pending===");
reject(111);
resolve(222);
});
// 当我们调用then的时候,应该需要两个变量来保存
promise.then(
(res) => {
console.log("res:", res);
},
(err) => {
console.log("err", err);
}
);
3.手写Promise-then方法优化1
// 1.状态的设计
const PROMISE_STATE_PENDING = "pending";
const PROMISE_STATE_FULFILED = "fulfiled";
const PROMISE_STATE_REJECTED = "rejected";
class MyPromise {
constructor(executor) {
this.status = PROMISE_STATE_PENDING;
this.value = null;
this.reason = null;
this.onfulfilledFns = [];
this.onrejectedFns = [];
const resolve = (value) => {
if (this.status === PROMISE_STATE_PENDING) {
queueMicrotask(() => {
this.status = PROMISE_STATE_FULFILED;
this.value = value;
console.log("resolve被调用了");
// 我们需要执行then传进来的第一个函数
// this.onfulfilled(this.value);
this.onfulfilledFns.forEach((fn) => fn(this.value));
});
}
};
const reject = (reason) => {
if (this.status === PROMISE_STATE_PENDING) {
queueMicrotask(() => {
this.status = PROMISE_STATE_REJECTED;
this.reason = reason;
console.log("reject被调用了");
// 我们需要执行then传进来的第二个函数
// this.onrejected(this.reason);
this.onrejectedFns.forEach((fn) => {
fn(this.reason);
});
});
}
};
executor(resolve, reject);
}
then(onfulfilled, onrejected) {
// 1.如果在then调用的时候,状态已经确定下来了
if (this.status === PROMISE_STATE_FULFILED && onfulfilled) {
onfulfilled(this.value);
}
if (this.status === PROMISE_STATE_REJECTED && onrejected) {
onrejected(this.reason);
}
// 2.将成功回调和失败的回调放到数组中
if (this.status === PROMISE_STATE_PENDING) {
this.onfulfilledFns.push(onfulfilled);
this.onrejectedFns.push(onrejected);
// this.onfulfilled = onfulfilled;
// this.onrejected = onrejected;
}
}
}
const promise = new MyPromise((resolve, reject) => {
console.log("传入的函数直接被调用了 pending===");
reject(111);
// resolve(222);
});
// 问题1: 调用then方法的多次调用
promise.then(
(res) => {
console.log("res===", res);
},
(err) => {
console.log("err===", err);
}
);
promise.then(
(res) => {
console.log("res2===", res);
},
(err) => {
console.log("err2===", err);
}
);
// 在确定Promise状态之后,在此调用我们的then
// 这是不会被回调的,因为前面放到函数遍历已经执行完了
setTimeout(() => {
promise.then((res) => {
console.log("res3---", res);
});
}, 1000);
4. 手写Promise-then方法优化2
// 1.状态的设计
const PROMISE_STATE_PENDING = "pending";
const PROMISE_STATE_FULFILED = "fulfiled";
const PROMISE_STATE_REJECTED = "rejected";
// 工具函数封装
function execFnTryAndCatchError(execFn, value, resolve, reject) {
try {
const result = execFn(value);
resolve(result);
} catch (err) {
reject(err);
}
}
class MyPromise {
constructor(executor) {
this.status = PROMISE_STATE_PENDING;
this.value = null;
this.reason = null;
this.onfulfilledFns = [];
this.onrejectedFns = [];
const resolve = (value) => {
if (this.status === PROMISE_STATE_PENDING) {
queueMicrotask(() => {
if (this.status !== PROMISE_STATE_PENDING) return;
this.status = PROMISE_STATE_FULFILED;
this.value = value;
// console.log("resolve被调用了");
this.onfulfilledFns.forEach((fn) => fn(this.value));
});
}
};
const reject = (reason) => {
if (this.status === PROMISE_STATE_PENDING) {
queueMicrotask(() => {
if (this.status !== PROMISE_STATE_PENDING) return;
this.status = PROMISE_STATE_REJECTED;
this.reason = reason;
// console.log("reject被调用了");
this.onrejectedFns.forEach((fn) => {
fn(this.reason);
});
});
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onfulfilled, onrejected) {
return new MyPromise((resolve, reject) => {
// 1.如果在then调用的时候,状态已经确定下来了
if (this.status === PROMISE_STATE_FULFILED && onfulfilled) {
// try {
// const value = onfulfilled(this.value);
// resolve(value);
// } catch (err) {
// reject(err);
// }
// 简写
execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
}
if (this.status === PROMISE_STATE_REJECTED && onrejected) {
// try {
// const reason = onrejected(this.reason);
// resolve(reason);
// } catch (err) {
// reject(err);
// }
execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
}
// 2.将成功回调和失败的回调放到数组中
if (this.status === PROMISE_STATE_PENDING) {
this.onfulfilledFns.push(() => {
// try {
// const value = onfulfilled(this.value);
// resolve(value);
// } catch (err) {
// reject(err);
// }
execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
});
this.onrejectedFns.push(() => {
// try {
// const reason = onrejected(this.reason);
// resolve(reason);
// } catch (err) {
// reject(err);
// }
execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
});
// this.onfulfilled = onfulfilled;
// this.onrejected = onrejected;
}
});
}
}
const promise = new MyPromise((resolve, reject) => {
console.log("状态 pending===");
// reject(111);
// throw new Error("executor error");
resolve(222);
});
promise
.then(
(res) => {
console.log("res1:", res);
return 'aaa'
// throw new Error("错误");
},
(err) => {
console.log("err1:", err);
return "bbb";
}
)
.then(
(res) => {
console.log("res2:", res);
},
// 只有上一个中抛出异常,才会来到这个catch
(err) => {
console.log("err2", err);
}
);
5. 手写Promise-catch方法设计
const PROMISE_STATE_PENDING = "pending";
const PROMISE_STATE_FULFILED = "fulfiled";
const PROMISE_STATE_REJECTED = "rejected";
function execFnTryAndCatchError(execFn, value, resolve, reject) {
try {
const result = execFn(value);
resolve(result);
} catch (err) {
reject(err);
}
}
class MyPromise {
constructor(executor) {
this.status = PROMISE_STATE_PENDING;
this.value = null;
this.reason = null;
this.onfulfilledFns = [];
this.onrejectedFns = [];
const resolve = (value) => {
if (this.status === PROMISE_STATE_PENDING) {
queueMicrotask(() => {
if (this.status !== PROMISE_STATE_PENDING) return;
this.status = PROMISE_STATE_FULFILED;
this.value = value;
// console.log("resolve被调用了");
this.onfulfilledFns.forEach((fn) => fn(this.value));
});
}
};
const reject = (reason) => {
if (this.status === PROMISE_STATE_PENDING) {
queueMicrotask(() => {
if (this.status !== PROMISE_STATE_PENDING) return;
this.status = PROMISE_STATE_REJECTED;
this.reason = reason;
// console.log("reject被调用了");
this.onrejectedFns.forEach((fn) => {
fn(this.reason);
});
});
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onfulfilled, onrejected) {
onrejected =
onrejected === undefined
? (err) => {
throw err;
}
: onrejected;
return new MyPromise((resolve, reject) => {
// 1.如果在then调用的时候,状态已经确定下来了
if (this.status === PROMISE_STATE_FULFILED && onfulfilled) {
execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
}
if (this.status === PROMISE_STATE_REJECTED && onrejected) {
execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
}
// 2.将成功回调和失败的回调放到数组中
if (this.status === PROMISE_STATE_PENDING) {
if (onfulfilled)
this.onfulfilledFns.push(() => {
execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
});
if (onrejected)
this.onrejectedFns.push(() => {
execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
});
}
});
}
catch(onrejected) {
this.then(undefined, onrejected);
}
}
const promise = new MyPromise((resolve, reject) => {
console.log("状态 pending===");
reject(111);
// throw new Error("executor error");
// resolve(222);
});
// 如果then第二个参数不传,就交给catch。如果传了,就给then第二个参数。
promise
.then((res) => {
console.log("res1:", res);
// throw new Error("错误");
})
.catch((err) => {
console.log("err1", err);
});
6. 手写Promise-finnally方法设计
const PROMISE_STATE_PENDING = "pending";
const PROMISE_STATE_FULFILED = "fulfiled";
const PROMISE_STATE_REJECTED = "rejected";
function execFnTryAndCatchError(execFn, value, resolve, reject) {
try {
const result = execFn(value);
resolve(result);
} catch (err) {
reject(err);
}
}
class MyPromise {
constructor(executor) {
this.status = PROMISE_STATE_PENDING;
this.value = null;
this.reason = null;
this.onfulfilledFns = [];
this.onrejectedFns = [];
const resolve = (value) => {
if (this.status === PROMISE_STATE_PENDING) {
queueMicrotask(() => {
if (this.status !== PROMISE_STATE_PENDING) return;
this.status = PROMISE_STATE_FULFILED;
this.value = value;
// console.log("resolve被调用了");
this.onfulfilledFns.forEach((fn) => fn(this.value));
});
}
};
const reject = (reason) => {
if (this.status === PROMISE_STATE_PENDING) {
queueMicrotask(() => {
if (this.status !== PROMISE_STATE_PENDING) return;
this.status = PROMISE_STATE_REJECTED;
this.reason = reason;
// console.log("reject被调用了");
this.onrejectedFns.forEach((fn) => {
fn(this.reason);
});
});
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onfulfilled, onrejected) {
onrejected =
onrejected === undefined
? (err) => {
throw err;
}
: onrejected;
const defaultOnFulfilled = (value) => {
return value;
};
onfulfilled = onfulfilled || defaultOnFulfilled;
return new MyPromise((resolve, reject) => {
// 1.如果在then调用的时候,状态已经确定下来了
if (this.status === PROMISE_STATE_FULFILED && onfulfilled) {
execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
}
if (this.status === PROMISE_STATE_REJECTED && onrejected) {
execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
}
// 2.将成功回调和失败的回调放到数组中
if (this.status === PROMISE_STATE_PENDING) {
if (onfulfilled)
this.onfulfilledFns.push(() => {
execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
});
if (onrejected)
this.onrejectedFns.push(() => {
execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
});
}
});
}
catch(onrejected) {
return this.then(undefined, onrejected);
}
// 不管成功还是失败,都调onfinally()
finally(onfinally) {
this.then(
() => {
onfinally();
},
() => {
onfinally();
}
);
}
}
const promise = new MyPromise((resolve, reject) => {
console.log("状态 pending===");
// reject(111);
// throw new Error("executor error");
resolve(222);
});
// 如果then第二个参数不传,就交给catch。如果传了,就给then第二个参数。
promise
.then((res) => {
console.log("res1:", res);
return "aaaa";
})
.catch((err) => {
console.log("err1", err);
})
.finally(() => {
console.log("最终");
});
6. 手写Promise-resolve-reject 方法设计
const PROMISE_STATE_PENDING = "pending";
const PROMISE_STATE_FULFILED = "fulfiled";
const PROMISE_STATE_REJECTED = "rejected";
function execFnTryAndCatchError(execFn, value, resolve, reject) {
try {
const result = execFn(value);
resolve(result);
} catch (err) {
reject(err);
}
}
class MyPromise {
constructor(executor) {
this.status = PROMISE_STATE_PENDING;
this.value = null;
this.reason = null;
this.onfulfilledFns = [];
this.onrejectedFns = [];
const resolve = (value) => {
if (this.status === PROMISE_STATE_PENDING) {
queueMicrotask(() => {
if (this.status !== PROMISE_STATE_PENDING) return;
this.status = PROMISE_STATE_FULFILED;
this.value = value;
// console.log("resolve被调用了");
this.onfulfilledFns.forEach((fn) => fn(this.value));
});
}
};
const reject = (reason) => {
if (this.status === PROMISE_STATE_PENDING) {
queueMicrotask(() => {
if (this.status !== PROMISE_STATE_PENDING) return;
this.status = PROMISE_STATE_REJECTED;
this.reason = reason;
// console.log("reject被调用了");
this.onrejectedFns.forEach((fn) => {
fn(this.reason);
});
});
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onfulfilled, onrejected) {
onrejected =
onrejected === undefined
? (err) => {
throw err;
}
: onrejected;
const defaultOnFulfilled = (value) => {
return value;
};
onfulfilled = onfulfilled || defaultOnFulfilled;
return new MyPromise((resolve, reject) => {
// 1.如果在then调用的时候,状态已经确定下来了
if (this.status === PROMISE_STATE_FULFILED && onfulfilled) {
execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
}
if (this.status === PROMISE_STATE_REJECTED && onrejected) {
execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
}
// 2.将成功回调和失败的回调放到数组中
if (this.status === PROMISE_STATE_PENDING) {
if (onfulfilled)
this.onfulfilledFns.push(() => {
execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
});
if (onrejected)
this.onrejectedFns.push(() => {
execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
});
}
});
}
catch(onrejected) {
return this.then(undefined, onrejected);
}
// 不管成功还是失败,都调onfinally()
finally(onfinally) {
this.then(
() => {
onfinally();
},
() => {
onfinally();
}
);
}
static resolve(value) {
return new MyPromise((resolve) => {
resolve(value)
})
}
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason)
})
}
}
MyPromise.resolve('hello world').then(res => {
console.log('res', res)
})
MyPromise.reject('hello world').catch(err => {
console.log('err', err)
})
7. 手写Promise-all-allSettled 方法设计
const PROMISE_STATE_PENDING = "pending";
const PROMISE_STATE_FULFILED = "fulfiled";
const PROMISE_STATE_REJECTED = "rejected";
function execFnTryAndCatchError(execFn, value, resolve, reject) {
try {
const result = execFn(value);
resolve(result);
} catch (err) {
reject(err);
}
}
class MyPromise {
constructor(executor) {
this.status = PROMISE_STATE_PENDING;
this.value = null;
this.reason = null;
this.onfulfilledFns = [];
this.onrejectedFns = [];
const resolve = (value) => {
if (this.status === PROMISE_STATE_PENDING) {
queueMicrotask(() => {
if (this.status !== PROMISE_STATE_PENDING) return;
this.status = PROMISE_STATE_FULFILED;
this.value = value;
// console.log("resolve被调用了");
this.onfulfilledFns.forEach((fn) => fn(this.value));
});
}
};
const reject = (reason) => {
if (this.status === PROMISE_STATE_PENDING) {
queueMicrotask(() => {
if (this.status !== PROMISE_STATE_PENDING) return;
this.status = PROMISE_STATE_REJECTED;
this.reason = reason;
// console.log("reject被调用了");
this.onrejectedFns.forEach((fn) => {
fn(this.reason);
});
});
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onfulfilled, onrejected) {
onrejected =
onrejected === undefined
? (err) => {
throw err;
}
: onrejected;
const defaultOnFulfilled = (value) => {
return value;
};
onfulfilled = onfulfilled || defaultOnFulfilled;
return new MyPromise((resolve, reject) => {
// 1.如果在then调用的时候,状态已经确定下来了
if (this.status === PROMISE_STATE_FULFILED && onfulfilled) {
execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
}
if (this.status === PROMISE_STATE_REJECTED && onrejected) {
execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
}
// 2.将成功回调和失败的回调放到数组中
if (this.status === PROMISE_STATE_PENDING) {
if (onfulfilled)
this.onfulfilledFns.push(() => {
execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
});
if (onrejected)
this.onrejectedFns.push(() => {
execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
});
}
});
}
catch(onrejected) {
return this.then(undefined, onrejected);
}
// 不管成功还是失败,都调onfinally()
finally(onfinally) {
this.then(
() => {
onfinally();
},
() => {
onfinally();
}
);
}
static resolve(value) {
return new MyPromise((resolve) => {
resolve(value)
})
}
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason)
})
}
static all(promises) {
// 问题关键: 什么时候要执行resolve,什么时候要执行reject
return new MyPromise((resolve, reject) => {
const values = []
promises.forEach(promise => {
promise.then((res) => {
values.push(res)
if (values.length === promises.length) resolve(values)
}, err => {
reject(err)
})
})
})
}
static allSettled(promises) {
return new MyPromise((resolve) => {
const results = []
promises.forEach(promise => {
promise.then(res => {
results.push({
status: PROMISE_STATE_FULFILED,
value: res
})
if (results.length === promises.length) resolve(results)
}, err => {
results.push({
status: PROMISE_STATE_REJECTED,
value: err
})
if (results.length === promises.length) resolve(results)
})
})
})
}
}
const p1 = new MyPromise((resolve) => {
setTimeout(() => { resolve(111) }, 1000);
})
const p2 = new MyPromise((resolve, reject) => {
setTimeout(() => { reject(222) }, 2000);
})
const p3 = new MyPromise((resolve) => {
setTimeout(() => { resolve(333) }, 3000);
})
// allSettled不会来到catch
MyPromise.allSettled([p1, p2, p3]).then((res) => {
console.log(res)
})
// MyPromise.all([p1, p2, p3]).then((res) => {
// console.log(res)
// }).catch(err => {
// console.log(err)
// })
8. 手写Promise-race-any 方法设计
const PROMISE_STATE_PENDING = "pending";
const PROMISE_STATE_FULFILED = "fulfiled";
const PROMISE_STATE_REJECTED = "rejected";
function execFnTryAndCatchError(execFn, value, resolve, reject) {
try {
const result = execFn(value);
resolve(result);
} catch (err) {
reject(err);
}
}
class MyPromise {
constructor(executor) {
this.status = PROMISE_STATE_PENDING;
this.value = null;
this.reason = null;
this.onfulfilledFns = [];
this.onrejectedFns = [];
const resolve = (value) => {
if (this.status === PROMISE_STATE_PENDING) {
queueMicrotask(() => {
if (this.status !== PROMISE_STATE_PENDING) return;
this.status = PROMISE_STATE_FULFILED;
this.value = value;
// console.log("resolve被调用了");
this.onfulfilledFns.forEach((fn) => fn(this.value));
});
}
};
const reject = (reason) => {
if (this.status === PROMISE_STATE_PENDING) {
queueMicrotask(() => {
if (this.status !== PROMISE_STATE_PENDING) return;
this.status = PROMISE_STATE_REJECTED;
this.reason = reason;
// console.log("reject被调用了");
this.onrejectedFns.forEach((fn) => {
fn(this.reason);
});
});
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onfulfilled, onrejected) {
onrejected =
onrejected === undefined
? (err) => {
throw err;
}
: onrejected;
const defaultOnFulfilled = (value) => {
return value;
};
onfulfilled = onfulfilled || defaultOnFulfilled;
return new MyPromise((resolve, reject) => {
// 1.如果在then调用的时候,状态已经确定下来了
if (this.status === PROMISE_STATE_FULFILED && onfulfilled) {
execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
}
if (this.status === PROMISE_STATE_REJECTED && onrejected) {
execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
}
// 2.将成功回调和失败的回调放到数组中
if (this.status === PROMISE_STATE_PENDING) {
if (onfulfilled)
this.onfulfilledFns.push(() => {
execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
});
if (onrejected)
this.onrejectedFns.push(() => {
execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
});
}
});
}
catch(onrejected) {
return this.then(undefined, onrejected);
}
// 不管成功还是失败,都调onfinally()
finally(onfinally) {
this.then(
() => {
onfinally();
},
() => {
onfinally();
}
);
}
static resolve(value) {
return new MyPromise((resolve) => {
resolve(value)
})
}
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason)
})
}
static all(promises) {
// 问题关键: 什么时候要执行resolve,什么时候要执行reject
return new MyPromise((resolve, reject) => {
const values = []
promises.forEach(promise => {
promise.then((res) => {
values.push(res)
if (values.length === promises.length) resolve(values)
}, err => {
reject(err)
})
})
})
}
static allSettled(promises) {
return new MyPromise((resolve) => {
const results = []
promises.forEach(promise => {
promise.then(res => {
results.push({
status: PROMISE_STATE_FULFILED,
value: res
})
if (results.length === promises.length) resolve(results)
}, err => {
results.push({
status: PROMISE_STATE_REJECTED,
value: err
})
if (results.length === promises.length) resolve(results)
})
})
})
}
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
promise.then(res => {
resolve(res)
}, err => {
resolve(err)
})
})
})
}
static any(promises) {
// resolve必须等到有一个成功的结果
// reject所有的都失败才执行reject
const reasons = [];
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
promise.then(resolve, err => {
reasons.push(err)
if (reasons.length === promises.length) reject(new AggregateError(reasons))
})
})
})
}
}
const p1 = new MyPromise((resolve, reject) => {
setTimeout(() => { reject(111) }, 1000);
})
const p2 = new MyPromise((resolve, reject) => {
setTimeout(() => { reject(222) }, 2000);
})
const p3 = new MyPromise((resolve, reject) => {
setTimeout(() => { reject(333) }, 3000);
})
MyPromise.any([p1, p2, p3]).then((res) => {
console.log(res)
}).catch(err => {
console.log(err)
})