Promise API
- 事件循环:https://www.youtube.com/watch?v=eiC58R16hb8&t=8s&ab_channel=LydiaHallie
- promise实现:深入分析 Promise 实现细节
只处理成功超简版
class Promise {
// 只处理成功
constructor(executor) {
this.cbs = [];
const resolve = (value) => {
queueMicrotask(() => {
this.data = value;
this.cbs.forEach((cb) => cb(value));
});
};
executor(resolve);
}
then(onResolved) {
return new Promise((resolve) => {
this.cbs.push(() => {
const res = onResolved(this.data);
if (res instanceof Promise) {
res.then(resolve);
} else {
resolve(res);
}
});
});
}
}
简单版本promise
- 包含then的链式调用
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(executor) {
this.value = undefined;
this.reason = undefined;
this.status = PENDING;
// 存放成功的回调
this.onFulfilledCallbacks = [];
// 存放失败的回调
this.onRejectedCallbacks = [];
const resolve = value => {
if (this.status === "pending") {
this.status = "fulfilled";
this.value = value;
// 依次将对应的函数执行
this.onFulfilledCallbacks.forEach(fn => fn());
}
};
const reject = reason => {
if (this.status === "pending") {
this.status = "rejected";
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
// executor内部执行一个异步任务
// 1. 当异步任务成功时调用resolve(value)
// 2. 失败时调用reject(reason)
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 工具函数, 判断function
isFunction(value) {
return typeof value === "function";
}
// 调用 then 方法来注册当promise状态改变时的回调
// 这些函数会被存储起来,等待promise状态改变时,才执行
// .then里面接收两个参数,一个是成功的回调,一个是失败的回调
// onFulfilled,onRejected => 是一个函数
then(onFulfilled, onRejected) {
// then().then() then可以传空值
onFulfilled = this.isFunction(onFulfilled) ? onFulfilled : val => val;
// prettier-ignore
onRejected = this.isFunction(onRejected)? onRejected : reason => {throw reason}
// 为了链式调用这里直接创建一个 MyPromise,并在后面 return 出去
const promise2 = new MyPromise((resolve, reject) => {
// fulfilled处理
const fulfilledMicrotask = () => {
// 创建一个微任务等待 promise2 完成初始化
queueMicrotask(() => {
try {
// 获取成功回调函数的执行结果
const x = onFulfilled(this.value);
// 传入 resolvePromise 集中处理
// this.resolvePromise(promise2, x, resolve, reject);
// x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
resolve(x);
} catch (e) {
reject(e);
}
});
};
// rejected处理
const rejectedMicrotask = () => {
queueMicrotask(() => {
try {
// 调用失败回调,并且把原因返回
const x = onRejected(this.reason);
// this.resolvePromise(promise2, x, resolve, reject);
// x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
resolve(x);
} catch (e) {
reject(e);
}
});
};
// 判断状态
switch (this.status) {
case FULFILLED: {
fulfilledMicrotask();
break;
}
case REJECTED: {
rejectedMicrotask();
break;
}
case PENDING: {
this.onFulfilledCallbacks.push(fulfilledMicrotask);
this.onRejectedCallbacks.push(rejectedMicrotask);
}
}
});
// then 返回promise2 实现链式调用
return promise2;
} // end then
}
// 测试test
const promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve("成功");
}, 1000);
}).then(
data => {
console.log("success", data);
return 666;
},
err => {
console.log("faild", err);
}
);
promise.then(value => console.log("Handler 1: ", value));
promise.then(value => console.log("Handler 2: ", value));
实例方法
- Promise.prototype.then()
- Promise.prototype.catch()
- Promise.prototype.finally()
静态方法
- Promise.all()
- Promise.race()
- Promise.allSettled()
- Promise.any()
- Promise.resolve()
- Promise.reject()
Promise.all
Promise.all 方法接受一个 promise 数组作为输入,并返回一个新的 promise,该 promise 等待所有的输入 promise 都完成。如果所有的 promise 都成功解决,新的 promise 将以一个包含所有解决值的数组形式解决。如果输入数组中的任何一个 promise 被拒绝,新的 promise 会立即以这个拒绝的原因被拒绝。
- 参数可迭代
- 返回值是promise
- 如果全部成功,状态变为resolve
- 但凡有一个失败,状态变为reject
// 判断参数是否是可迭代对象
function isIterable(obj) {
// 检查对象是否为 null 或 undefined
return obj != null && typeof obj[Symbol.iterator] === 'function';
}
function promiseAll(promises) {
// 1. 首先判断参数是否是可迭代对象
if (!isIterable(promises)) {
return new TypeError(`${promises} is not iterable`)
}
return new Promise((resolve, reject) => {
let result = [] // 存放结果
let count = 0 // 进入fullfilled的promise个数
promises.forEach((p, i) => {
// 包装非promise值,保证可迭代元素为promise
Promise.resolve(p)
.then((res) => {
result[i] = res
// 当所有的都resolve了,resolve
if (++count === promises.length) resolve(result)
})
// 只要有一个reject,就reject出去
.catch((err) => reject(err))
})
})
}
Promise.race
Promise.race()
方法接收一个 promise 数组作为参数,并返回一个新的 promise 对象。这个新返回的 promise 等待参数数组中的第一个完成的 promise,并采用它的状态(fulfilled 或 rejected)
function promiseRace(promises) {
return new Promise((resolve, reject) => {
promises.forEach(promise => {
// 当任何一个promise解决或拒绝时,由于resolve()和reject()会改变promise的状态,
// 所以只有第一个状况会被处理
Promise.resolve(promise)
.then(value => resolve(value))
.catch(error => reject(error));
});
});
}
Promise.allSettled
Promise.allSettled()
方法接受一个数组作为参数,数组的每个成员都是一个 Promise 对象,并返回一个新的 Promise 对象。只有等到参数数组的所有 Promise 对象都发生状态变更(不管是fulfilled还是rejected),返回的 Promise 对象才会发生状态变更。
function promiseAllSettled(promises) {
let wrappedPromises = promises.map(promise =>
Promise.resolve(promise)
.then(
value => ({ status: 'fulfilled', value }),
reason => ({ status: 'rejected', reason }),
)
);
return Promise.all(wrappedPromises);
}
// 示例
let promise1 = Promise.resolve('Promise 1');
let promise2 = Promise.reject('Promise 2');
promiseAllSettled([promise1, promise2])
.then(results => console.log(results));
对每个 Promise 对象使用 Promise.resolve()
方法和添加 .then()
,将每个 Promise 包装成一个永远不会被拒绝的新 Promise,这个新的 Promise 总是解决并给出描述原始 Promise 结果的对象
Promise.any
只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。 Promise.any()跟Promise.race()方法很像,只有一点不同,就是Promise.any()不会因为某个 Promise 变成rejected状态而结束,必须等到所有参数 Promise 变成rejected状态才会结束。
function promiseAny(promises) {
return new Promise((resolve, reject) => {
// 存错误状态
let errors = [];
promises.forEach(promise => {
Promise.resolve(promise)
.then(value => resolve(value))
.catch(error => {
errors.push(error);
// 当所有的都Error了,才reject
if(errors.length === promises.length) {
reject(new AggregateError(errors, "All promises were rejected"));
}
})
});
});
}
Promise.resolve
// resolve 静态方法
static resolve (value) {
// 如果传入 MyPromise 就直接返回
if (value instanceof MyPromise) return value
// 普通值,创建promise对象
return new MyPromise(resolve => resolve(value))
}
// Promise.resolve() 方法的实现
function promiseResolve(value) {
// 是Promise实例,直接返回即可
if (value instanceof Promise) return value
return new Promise((resolve) => {
resolve(value);
});
}
Promise.reject
// reject 静态方法
static reject (reason) {
return new MyPromise((resolve, reject) => {
reject(reason)
})
}
function promiseReject(reason) {
return new Promise((_, reject) => {
reject(reason);
});
}
_.prototype.catch()
实例方法
// catch方法实际上是一个没有onResolved,只有onRejected参数的特别的then方法:
this.catch = function (errCallback) {
return this.then(null, errCallback);
};
// 原型上挂载
Promise.prototype.catch = function(errCallback){
return this.then(undefined,errCallback)
}
// 构造函数中写法
catch (failCallback) {
return this.then(undefined, failCallback)
}
eg.
const p = () => {
return new Promise((resolve,reject)=>{
reject('失败了哦')
})
}
p().then(value => console.log(value))
.catch(reason => console.log(reason))
// failCallback ::: reason => console.log(reason)
_.prototype.finally()
- 无论当前promise状态是成功或者失败,finally中的回调始终会执行一次
- 在finally()方法的后面可以链式调用then方法,拿到当前promise对象最终返回的结果
// finally方法用于注册一个在Promise结束时,无论结果是fulfilled还是rejected都会执行的回调函数。
this.finally = function (callback) {
return this.then(
value => MyPromise.resolve(callback()).then(() => value),
reason => MyPromise.resolve(callback()).then(() => { throw reason })
);
};
// class Mypromise中写法
finally (callback) {
return this.then(
// Promise包装是保证异步等待执行后面的then方法
value => MyPromise.resolve(callback()).then(() => value),
// throw reason
reason => return MyPromise.resolve(callback()).then(() => {throw reason})
)
}