Promise.race()
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
Promise.race()
静态方法采用可迭代的 Promise 作为输入并返回单个 Promise
。这个返回的 Promise 将随着第一个 Promise 的最终状态而确定。
¥The Promise.race()
static method takes an iterable of promises as input and returns a single Promise
. This returned promise settles with the eventual state of the first promise that settles.
Try it
语法
参数
返回值
¥Return value
与 iterable
中第一个 Promise 的最终状态异步结算的 Promise
。换句话说,如果第一个解决的承诺得到履行,它就实现,如果第一个解决的承诺被拒绝,它就拒绝。如果传递的 iterable
为空,则返回的 Promise 将永远保持未决状态。如果传递的 iterable
非空但不包含待处理的 Promise,则返回的 Promise 仍然是异步(而不是同步)结算的。
¥A Promise
that asynchronously settles with the eventual state of the first promise in the iterable
to settle. In other words, it fulfills if the first promise to settle is fulfilled, and rejects if the first promise to settle is rejected. The returned promise remains pending forever if the iterable
passed is empty. If the iterable
passed is non-empty but contains no pending promises, the returned promise is still asynchronously (instead of synchronously) settled.
描述
¥Description
Promise.race()
方法是 承诺并发 方法之一。当你希望第一个异步任务完成,但不关心其最终状态(即它可以成功或失败)时,它非常有用。
¥The Promise.race()
method is one of the promise concurrency methods. It's useful when you want the first async task to complete, but do not care about its eventual state (i.e. it can either succeed or fail).
如果可迭代包含一个或多个非承诺值和/或已解决的承诺,则 Promise.race()
将解决为可迭代中找到的第一个值。
¥If the iterable contains one or more non-promise values and/or an already settled promise, then Promise.race()
will settle to the first of these values found in the iterable.
示例
使用 Promise.race()
¥Using Promise.race()
此示例展示了如何使用 Promise.race()
来竞争使用 setTimeout()
实现的多个计时器。时间最短的计时器总是赢得比赛并成为最终承诺的状态。
¥This example shows how Promise.race()
can be used to race several timers implemented with setTimeout()
. The timer with the shortest time always wins the race and becomes the resulting promise's state.
function sleep(time, value, state) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (state === "fulfill") {
return resolve(value);
} else {
return reject(new Error(value));
}
}, time);
});
}
const p1 = sleep(500, "one", "fulfill");
const p2 = sleep(100, "two", "fulfill");
Promise.race([p1, p2]).then((value) => {
console.log(value); // "two"
// Both fulfill, but p2 is faster
});
const p3 = sleep(100, "three", "fulfill");
const p4 = sleep(500, "four", "reject");
Promise.race([p3, p4]).then(
(value) => {
console.log(value); // "three"
// p3 is faster, so it fulfills
},
(error) => {
// Not called
},
);
const p5 = sleep(500, "five", "fulfill");
const p6 = sleep(100, "six", "reject");
Promise.race([p5, p6]).then(
(value) => {
// Not called
},
(error) => {
console.error(error.message); // "six"
// p6 is faster, so it rejects
},
);
Promise.race 的异步性
¥Asynchronicity of Promise.race
以下示例演示了 Promise.race
的异步性。与其他 Promise 并发方法不同,Promise.race
始终是异步的:即使 iterable
为空,它也不会同步稳定。
¥This following example demonstrates the asynchronicity of Promise.race
. Unlike other promise concurrency methods, Promise.race
is always asynchronous: it never settles synchronously, even when the iterable
is empty.
// Passing an array of promises that are already resolved,
// to trigger Promise.race as soon as possible
const resolvedPromisesArray = [Promise.resolve(33), Promise.resolve(44)];
const p = Promise.race(resolvedPromisesArray);
// Immediately logging the value of p
console.log(p);
// Using setTimeout, we can execute code after the stack is empty
setTimeout(() => {
console.log("the stack is now empty");
console.log(p);
});
// Logs, in order:
// Promise { <state>: "pending" }
// the stack is now empty
// Promise { <state>: "fulfilled", <value>: 33 }
空的迭代会导致返回的承诺永远处于待处理状态:
¥An empty iterable causes the returned promise to be forever pending:
const foreverPendingPromise = Promise.race([]);
console.log(foreverPendingPromise);
setTimeout(() => {
console.log("the stack is now empty");
console.log(foreverPendingPromise);
});
// Logs, in order:
// Promise { <state>: "pending" }
// the stack is now empty
// Promise { <state>: "pending" }
如果可迭代包含一个或多个非承诺值和/或已确定的承诺,则 Promise.race
将确定为数组中找到的第一个值:
¥If the iterable contains one or more non-promise value and/or an already settled promise, then Promise.race
will settle to the first of these values found in the array:
const foreverPendingPromise = Promise.race([]);
const alreadyFulfilledProm = Promise.resolve(100);
const arr = [foreverPendingPromise, alreadyFulfilledProm, "non-Promise value"];
const arr2 = [foreverPendingPromise, "non-Promise value", Promise.resolve(100)];
const p = Promise.race(arr);
const p2 = Promise.race(arr2);
console.log(p);
console.log(p2);
setTimeout(() => {
console.log("the stack is now empty");
console.log(p);
console.log(p2);
});
// Logs, in order:
// Promise { <state>: "pending" }
// Promise { <state>: "pending" }
// the stack is now empty
// Promise { <state>: "fulfilled", <value>: 100 }
// Promise { <state>: "fulfilled", <value>: "non-Promise value" }
使用 Promise.race()实现请求超时
¥Using Promise.race() to implement request timeout
你可以使用拒绝的计时器来竞争可能持久的请求,这样当时间限制过去时,生成的承诺会自动拒绝。
¥You can race a potentially long-lasting request with a timer that rejects, so that when the time limit has elapsed, the resulting promise automatically rejects.
const data = Promise.race([
fetch("/api"),
new Promise((resolve, reject) => {
// Reject after 5 seconds
setTimeout(() => reject(new Error("Request timed out")), 5000);
}),
])
.then((res) => res.json())
.catch((err) => displayError(err));
如果 data
承诺履行,它将包含从 /api
获取的数据;否则,如果 fetch
保持等待 5 秒,它将拒绝并输掉与 setTimeout
计时器的比赛。
¥If the data
promise fulfills, it will contain the data fetched from /api
; otherwise, it will reject if fetch
remains pending for 5 seconds and loses the race with the setTimeout
timer.
使用 Promise.race() 检测 Promise 的状态
¥Using Promise.race() to detect the status of a promise
因为 Promise.race()
解析为可迭代中的第一个非挂起的 Promise,所以我们可以检查 Promise 的状态,包括它是否处于挂起状态。本示例改编自 promise-status-async
。
¥Because Promise.race()
resolves to the first non-pending promise in the iterable, we can check a promise's state, including if it's pending. This example is adapted from promise-status-async
.
function promiseState(promise) {
const pendingState = { status: "pending" };
return Promise.race([promise, pendingState]).then(
(value) =>
value === pendingState ? value : { status: "fulfilled", value },
(reason) => ({ status: "rejected", reason }),
);
}
在此函数中,如果 promise
处于待决状态,则第二个值 pendingState
(非承诺)将成为竞赛结果;否则,如果 promise
已经解决,我们可以通过 onFulfilled
和 onRejected
处理程序知道它的状态。例如:
¥In this function, if promise
is pending, the second value, pendingState
, which is a non-promise, becomes the result of the race; otherwise, if promise
is already settled, we may know its state through the onFulfilled
and onRejected
handlers. For example:
const p1 = new Promise((res) => setTimeout(() => res(100), 100));
const p2 = new Promise((res) => setTimeout(() => res(200), 200));
const p3 = new Promise((res, rej) => setTimeout(() => rej(300), 100));
async function getStates() {
console.log(await promiseState(p1));
console.log(await promiseState(p2));
console.log(await promiseState(p3));
}
console.log("Immediately after initiation:");
getStates();
setTimeout(() => {
console.log("After waiting for 100ms:");
getStates();
}, 100);
// Logs:
// Immediately after initiation:
// { status: 'pending' }
// { status: 'pending' }
// { status: 'pending' }
// After waiting for 100ms:
// { status: 'fulfilled', value: 100 }
// { status: 'pending' }
// { status: 'rejected', reason: 300 }
注意:
promiseState
函数仍然异步运行,因为即使已经解决,也无法同步获取 Promise 的值(即没有then()
或await
)。然而,promiseState()
总是在一个周期内完成,并且从不真正等待任何承诺的结算。¥Note: The
promiseState
function still runs asynchronously, because there is no way to synchronously get a promise's value (i.e. withoutthen()
orawait
), even when it is already settled. However,promiseState()
always fulfills within one tick and never actually waits for any promise's settlement.
与 Promise.any() 的比较
¥Comparison with Promise.any()
Promise.race
取得第一个结算的 Promise
。
¥Promise.race
takes the first settled Promise
.
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "one");
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(reject, 100, "two");
});
Promise.race([promise1, promise2])
.then((value) => {
console.log("succeeded with value:", value);
})
.catch((reason) => {
// Only promise1 is fulfilled, but promise2 is faster
console.error("failed with reason:", reason);
});
// failed with reason: two
Promise.any
取第一个已履行的 Promise
。
¥Promise.any
takes the first fulfilled Promise
.
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "one");
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(reject, 100, "two");
});
Promise.any([promise1, promise2])
.then((value) => {
// Only promise1 is fulfilled, even though promise2 settled sooner
console.log("succeeded with value:", value);
})
.catch((reason) => {
console.error("failed with reason:", reason);
});
// succeeded with value: one
规范
Specification |
---|
ECMAScript Language Specification # sec-promise.race |
浏览器兼容性
BCD tables only load in the browser