静态方法
刀刀
8/8/2025
0 字
0 分钟
与 catch
和 finally
类似,Promise A+ 的标准只包含了 .then
,并没有包含其余的方法,这些方法都是 ES6 标准中新增的,因此 A+ 规范的文档没有这些事件的描述。推荐去 MDN 查看。
resolve
根据 MDN 的描述,Promise.resolve(value)
方法返回一个以给定值解析后的 Promise
对象。如果该值是一个 thenable
(即带有 then
方法的对象),返回的 Promise
将“跟随”这个 thenable
,采用它的最终状态;否则返回的 Promise
将以此值完成。
翻译成大白话就是,Promise.resolve()
会把值转为 Promise
,但是分三种情况:
- 值本来就是
Promise
—— 不转换直接返回 - 值是
thenable
对象(即有then
方法)—— 返回then
方法 - 都不是,直接
resolve
返回该值
分析至此,resolve
方法只需要添加一些判断即可。
class MyPromise {
// ...
static resolve(value) {
// 该值本身就是一个 Promise,那么该 Promise 将被返回
if (value instanceof Promise) {
return value;
}
return new Promise((resolve, reject) => {
if (isPromiseLike(value)) {
value.then(resolve, reject);
} else {
resolve(value);
}
});
}
}
reject
根据 MDN 文档来看,Promise.reject(reason)
方法返回一个被拒绝的 Promise
对象,参数 reason
会被传递给被拒绝的回调函数。Promise.reject()
实际上相当于 new Promise((resolve, reject) => reject(reason))
的简写形式。
特别注意
与 Promise.resolve()
不同,即使 reason
已经是一个 Promise
对象,Promise.reject()
方法也始终会将其封装在一个新的 Promise
对象中。
class MyPromise {
// ...
static resolve(value) {
// 该值本身就是一个 Promise,那么该 Promise 将被返回
if (value instanceof Promise) {
return value;
}
return new Promise((resolve, reject) => {
if (isPromiseLike(value)) {
value.then(resolve, reject);
} else {
resolve(value);
}
});
}
static reject(reason) {
return new Promise((_, reject) => {
reject(reason);
});
}
}
try
Promise.try
主要是用于处理同步代码,在 Promise
之外抛出的异常,可以通过 Promise.try
来捕获。
下面来看一个代码:
function fn () {
throw new Error('错误')
return 1
}
Promise.resolve(fn()).then(
(res) => {
console.log(res)
},
(err) => {
console.log(err)
}
)
预期的结果是 console.log(err)
,但是实际结果是代码报错,这说明 fn
函数同步报错,是不会进入 Promise
里,自然不会被 onRejected
捕获。因此需要使用 Promise.try
来处理。
try
方法实际上返回的也是一个 new Promise
,接收一个 callback
回调函数,调用 resolve
修改状态并返回执行结果即可。这里不需要使用 try...catch
去捕获错误,因为最终会走到构造器里,构造器会捕获错误并修改状态。
class MyPromise {
// ...
static resolve(value) {
// 该值本身就是一个 Promise,那么该 Promise 将被返回
if (value instanceof Promise) {
return value;
}
return new Promise((resolve, reject) => {
if (isPromiseLike(value)) {
value.then(resolve, reject);
} else {
resolve(value);
}
});
}
static reject(reason) {
return new Promise((_, reject) => {
reject(reason);
});
}
static try(callback, ...args) {
return new Promise((resolve) => {
resolve(callback(...args));
});
}
}
all
根据 MDN 可知,all
方法接收一个可迭代的数据,并会按照顺序返回一个数组,数组中的每一项都是 Promise
的结果。如果有一个 Promise
失败,则返回第一个失败的 Promise
的结果。
因此需要注意以下几点:
- 接收的值是可迭代的,包括数组、字符串、
Map
和Set
等,为了更好的操作,用扩展运算符[...]
转为数组 - 返回的是一个
new MyPromise
,遍历转换好的数组,调用MyPromise.resolve()
方法,将每一个值转为Promise
,在.then
方法中把执行的结果按顺序保存到数组内 - 声明一个变量,用于判断当前执行完毕几个
Promise
,当执行完毕的Promise
数量与数组长度一致时,说明所有Promise
都执行完毕,此时返回结果
class MyPromise {
// ...
static resolve(value) {
// 该值本身就是一个 Promise,那么该 Promise 将被返回
if (value instanceof Promise) {
return value;
}
return new Promise((resolve, reject) => {
if (isPromiseLike(value)) {
value.then(resolve, reject);
} else {
resolve(value);
}
});
}
static reject(reason) {
return new Promise((_, reject) => {
reject(reason);
});
}
static try(callback, ...args) {
return new Promise((resolve) => {
resolve(callback(...args));
});
}
static all(promises) {
promises = [...promises]
return new MyPromise((resolve, reject) => {
let result = [] // 存储结果
// 如果没传,则返回空数组
if (promises.length <= 0) resolve(result)
let count = 0 // 当前执行完成的 Promise 数量
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then((res) => {
count++
result[index] = res
// 如果执行完成数量与数组长度相等,说明都执行完毕了
if (count === promises.length) {
resolve(result)
}
}, reject)
})
})
}
}
需要注意的是,在保存值时,不能直接使用 push
方法存储。因为 Promise.all
方法是按照传入的顺序来存储结果。如果使用 push
方法,则会变成最先执行完毕的最先存储,顺序就不一致了。