Promise 的方法:.all()、.any()、.finally()、.race()
在本系列的前几篇文章中,我展示了Promise的resolve
和方法,以及如何使用和方法从Promise中检索数据。 [ https://dev.to/swarnaliroy94/retrieving-data-from-promise-then-catch-3onk ]reject
Promise.then()
Promise.catch()
我们可以使用项目中最常用的方法来简化这个过程Async/Await
。不过,在介绍Async/Await之前,我想先让读者熟悉一下 Promise 的其他一些方法。
我将在这篇文章中展示的方法是Promise.all()
、、& Promise.race()
。Promise.any()
Promise.finally()
那我们开始吧!!
◼️ Promise.all() 方法
👉 该Promise.all()
方法接受一个可迭代的对象,例如一个承诺数组作为输入,并返回一个解析为输入承诺的结果数组的承诺。 👉 当所有输入的承诺都已解决或可迭代输入不包含承诺时,返回的承诺将被解决。 👉当输入承诺拒绝或非承诺引发错误时, 它会立即拒绝,并将使用第一个拒绝消息/错误消息拒绝。 👉 当涉及许多异步任务时,它通常用于整个代码依赖于成功运行 - 我们希望在继续执行代码之前完成所有这些任务。 👉 此方法聚合多个承诺 的结果。
Promise.all() 的实现
🔹 当传递一个空的可迭代对象时,此方法返回的 Promise 将被同步执行。解析后的值将是一个空数组。🔹
当传递一个非空的可迭代对象时,如果所有 Promise都已实现或都不是 Promise,则此方法返回的 Promise 将被异步执行。
以下是方法的示例Promise.all()
👇
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 300, "resolved");
}); //will be resolved after 300ms
const promise2 = 93; //non-promise
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "resolved2");
}); // will be resolved after 100ms
Promise.all([promise1, promise2, promise3])
.then((values) => {
console.log(values);
})
.catch((err) => {
console.log(err);
});
//expected output: [ 'resolved', 93, 'resolved2' ]
Promise.all() 的拒绝:快速失败行为
Promise.all()
显示快速失败行为,即,如果传入的任何元素被拒绝,则 Promise.all() 会异步拒绝,并使用被拒绝的承诺的值。
例如,如果我们传入两个在超时后 resolve 的 Promise 和一个立即 throw 的Promise ,那么Promise.all()就会立即 throw 。它不依赖于其他 Promise 是否已经resolve。以下示例就是这么做的!
const pro1 = new Promise((resolve, reject) => {
setTimeout(() => resolve("one"), 1000);
});
const pro2 = new Promise((resolve, reject) => {
setTimeout(() => resolve("two"), 2000);
});
const pro3 = new Promise((resolve, reject) => {
setTimeout(() => reject("rejected"), 3000);
});
Promise.all([pro1, pro2, pro3])
.then((values) => {
console.log(values);
})
.catch((error) => {
console.log(error);
});
//expected output: rejected
让我们转到另一种方法Promise.any()
。
◼️ Promise.any() 方法
👉Promise.any()
接受一个可迭代的对象,例如一个承诺数组作为输入。一旦承诺得到履行,就会返回一个承诺,并使用该承诺的值来解决
该承诺。👉 如果可迭代的履行中没有承诺(如果所有给定的承诺都被拒绝),则返回的承诺将被拒绝,并出现AggregateError(将各个错误组合在一起)。
Promise.any() 的实现
🔹 与 不同Promise.all()
,此方法用于返回第一个满足 的promise。🔹它 在promise完成后立即短路,因此一旦 promise满足,它就不会等待其他 promise完成。🔹 当传递非空可迭代对象时,并且任何 promise 满足或为非 promise,则此方法返回的 promise 将异步满足。
例如,以下代码片段将首先解析QuickyDone 的Promise,因为它在100ms后解析完成,而另一个 Promise 在500ms后解析完成。它不会等待任何其他 Promise 完成,而是立即返回第一个解析完成的 Promise。
const SlowlyDone = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "Done slowly");
}); //resolves after 500ms
const QuicklyDone = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "Done quickly");
}); //resolves after 100ms
const Rejection = new Promise((resolve, reject) => {
setTimeout(reject, 100, "Rejected"); //always rejected
});
Promise.any([SlowlyDone, QuicklyDone, Rejection])
.then((value) => {
console.log(value);
// QuicklyDone fulfils first
})
.catch((err) => {
console.log(err);
});
//expected output: Done quickly
Promise.any() 的拒绝
🔹 如果没有 Promise 履行,Promise.any() 会拒绝并抛出 AggregateError 错误。🔹 AggregateError
对象表示需要将多个错误包装在一个错误中时出现的错误。当操作需要报告多个错误时,会抛出该错误。
下面是一个例子👇
const Rejection = new Promise((resolve, reject) => {
setTimeout(reject, 100, "Rejected"); //always rejected
});
Promise.any([Rejection])
.catch((err) => {
console.log(err);
});
// expected output: "AggregateError: No Promise in Promise.any was resolved"
⭐ 注意,Promise.any() 在node.js 15.0.0中受支持。如果你的 node.js 版本低于此版本,控制台可能会显示TypeError: Promise.any is not a function错误,因此你需要更新版本并重试。
◼️ Promise.prototype.finally()
👉 该finally()
方法返回一个Promise。
👉 当 Promise完成(无论是解决还是拒绝)时,都会执行此指定的回调函数。
👉 这有助于避免在承诺的 then() 和 catch() 处理程序中重复代码。
👉 如果您要在做出承诺后进行任何处理或清理工作,无论结果如何,finally() 方法都会有所帮助。
以下是此方法的一个简单示例。👇
const addition = (a, b) =>
new Promise((resolve, reject) => {
if (typeof a == "number" && typeof b == "number") {
resolve(a + b);
} else {
reject("Not a Number");
}
});
addition(10, 5)
.then((response) => {
console.log(response);
})
.catch((err) => {
console.log(err);
})
.finally(() => {
console.log("Numbers are added");
});
/* expected output: 15
Numbers are added */
◼️ Promise.race() 方法
👉只要可迭代对象(例如数组)中的一个承诺通过该承诺的值或原因实现或拒绝,该Promise.race()
方法就会返回一个已解决或已拒绝的Promise 。 👉如果传递的可迭代对象为空, 则返回的承诺将永远处于待处理状态。 👉如果可迭代对象包含一个或多个非承诺值或已解决的承诺,则将解析为在可迭代对象中找到的第一个值。Promise.race()
让我们看一个带有 setTimeout 的Promise.race()的示例👇
const pro1 = new Promise((resolve, reject) => {
setTimeout(() => resolve("one"), 200);
});
const pro2 = new Promise((resolve, reject) => {
setTimeout(() => resolve("two"), 100);
});
Promise.race([pro1, pro2])
.then((response) => {
console.log(response); //output: two
})
.catch((err) => {
console.log(err);
});
const pro3 = new Promise((resolve, reject) => {
setTimeout(() => reject("rejected"), 300);
});
const pro4 = new Promise((resolve, reject) => {
setTimeout(() => resolve("four"), 400);
});
Promise.race([pro3, pro4])
.then((response) => {
console.log(response);
})
.catch((err) => {
console.log(err);
}); //output: rejected
在第一种情况下,pro2(100ms)比pro1(200ms)快,因此输出显示two。在第二种情况下,pro3(300ms)比pro4(400ms)快,因此 Promise 被拒绝。所以,Promise.race() 基本上会接受第一个已解决的 Promise。
如果我们采用同样的例子并传递里面的所有承诺Promise.race()
,它将返回两个作为输出,因为pro2是这种情况下解决的最快的承诺。
const pro1 = new Promise((resolve, reject) => {
setTimeout(() => resolve("one"), 200);
});
const pro2 = new Promise((resolve, reject) => {
setTimeout(() => resolve("two"), 100);
});
const pro3 = new Promise((resolve, reject) => {
setTimeout(() => reject("rejected"), 300);
});
const pro4 = new Promise((resolve, reject) => {
setTimeout(() => resolve("four"), 400);
});
Promise.race([pro1, pro2, pro3, pro4])
.then((response) => {
console.log(response);
})
.catch((err) => {
console.log(err);
});
//output: two