
在 JavaScript 中,Promise 是一种用于处理异步操作的对象,它让我们可以更优雅地处理异步任务,避免了回调地狱的问题。而 Promise.race 作为 Promise 组合的重要方法之一,有着独特的应用场景。本文将深入探讨 Promise.race 的原理、用法以及实际应用。
Promise.race 方法接收一个可迭代对象(通常是数组)作为参数,这个数组中的每个元素都应该是一个 Promise 对象。它会返回一个新的 Promise 实例,这个新 Promise 会在数组中的任何一个 Promise 率先解决(resolved)或拒绝(rejected)时,立即以相同的状态和结果进行解决或拒绝。其基本语法如下:
Promise.race(iterable);
Promise.race 就像是一场赛跑,数组中的每个 Promise 都是一名选手。一旦有一个选手冲过终点线(即 Promise 被解决或拒绝),比赛就结束了,Promise.race 返回的新 Promise 也会以这个率先完成的 Promise 的状态和结果为准。
const promise1 = new Promise((resolve, reject) => {setTimeout(() => {resolve('Promise 1 resolved');}, 1000);});const promise2 = new Promise((resolve, reject) => {setTimeout(() => {resolve('Promise 2 resolved');}, 2000);});Promise.race([promise1, promise2]).then((result) => {console.log(result); // 输出: Promise 1 resolved}).catch((error) => {console.error(error);});
在这个例子中,promise1 会在 1 秒后解决,而 promise2 会在 2 秒后解决。由于 promise1 率先完成,所以 Promise.race 返回的 Promise 会以 promise1 的解决结果进行解决,最终输出 Promise 1 resolved。
在实际开发中,我们经常会遇到网络请求,但有时候请求可能会因为各种原因(如服务器故障、网络延迟等)而长时间没有响应。这时,我们可以使用 Promise.race 来设置请求超时,避免用户长时间等待。
function fetchWithTimeout(url, timeout) {const fetchPromise = fetch(url);const timeoutPromise = new Promise((_, reject) => {setTimeout(() => {reject(new Error('Request timed out'));}, timeout);});return Promise.race([fetchPromise, timeoutPromise]);}fetchWithTimeout('https://api.example.com/data', 5000).then((response) => {if (response.ok) {return response.json();}throw new Error('Network response was not ok');}).then((data) => {console.log(data);}).catch((error) => {console.error(error);});
在这个例子中,我们创建了两个 Promise:一个是 fetchPromise 用于发起网络请求,另一个是 timeoutPromise 用于设置超时。使用 Promise.race 将这两个 Promise 组合起来,如果在 5 秒内请求没有完成,timeoutPromise 会率先拒绝,从而触发 catch 块,提示用户请求超时。
当我们需要从多个数据源加载相同或相似的资源时,可以使用 Promise.race 来选择最快返回结果的数据源。
const source1 = new Promise((resolve) => {setTimeout(() => {resolve('Data from source 1');}, 2000);});const source2 = new Promise((resolve) => {setTimeout(() => {resolve('Data from source 2');}, 1000);});Promise.race([source1, source2]).then((data) => {console.log(data); // 输出: Data from source 2}).catch((error) => {console.error(error);});
在这个例子中,我们模拟了从两个不同数据源加载数据的过程。由于 source2 会在 1 秒后返回数据,而 source1 会在 2 秒后返回数据,所以 Promise.race 会选择 source2 的结果。
| 特性 | 详情 |
|---|---|
| 语法 | Promise.race(iterable) |
| 原理 | 多个 Promise 竞争,率先完成的 Promise 决定 Promise.race 返回 Promise 的状态和结果 |
| 应用场景 | 设置请求超时、竞争加载资源等 |
Promise.race 为我们处理异步操作提供了一种强大而灵活的方式,通过合理运用它,我们可以优化代码逻辑,提高应用的性能和用户体验。在实际开发中,当我们需要处理多个异步任务并关注最快完成的结果时,不妨考虑使用 Promise.race。