Promise.race
和Promise.all
是性格相对的兄弟。之前已经带大家实现过Promise.all
,可以看完那篇之后,对照着来看今天这篇,本文将介绍如何使用JavaScript
手写实现Promise.race
的功能和逻辑。
Promise.race
是一个静态方法,它接受一个可迭代对象作为参数,返回一个新的Promise
对象。这个新的Promise
对象的状态和值取决于可迭代对象中最先完成的Promise
对象。如果可迭手对象为空,那么返回的Promise
对象将永远处于pending
状态。如果可迭代对象中有非Promise
对象,那么返回的Promise
对象将立即以该值为fulfilled
状态。
在某些情况下,我们可能需要在一定时间内完成某个异步操作,否则就取消或者报错。这样可以避免一些不必要的等待或者资源浪费。例如,我们可能需要在5秒内获取一个网络请求的结果,如果超过5秒还没有返回,就认为请求失败。这时候,我们可以使用Promise.race
来实现一个超时机制。
Promise.race
接受一个可迭代对象作为参数,返回一个新的Promise
对象。这个新的Promise
对象的状态和值取决于可迭代对象中最先完成的Promise
对象。所以,我们可以将一个网络请求的Promise
和一个延迟拒绝的Promise
放入Promise.race
中,这样如果网络请求在指定时间内没有返回结果,就会触发延迟拒绝的Promise
,从而实现超时错误。
下面是一个使用fetch API
和setTimeout
来实现超时机制的代码示例
js// 定义一个延迟拒绝的Promise
function timeoutPromise (ms, message) {
return new Promise((_, reject) => {
setTimeout(() => {
reject(new Error(message));
}, ms);
});
}
// 使用fetch API发送一个网络请求
function fetchRequest (url) {
return fetch(url).then((res) => res.json());
}
// 使用Promise.race实现超时机制
function fetchWithTimeout (url, ms, message) {
return Promise.race([fetchRequest(url), timeoutPromise(ms, message)]);
}
// 调用函数,如果5秒内没有返回结果,就抛出错误
fetchWithTimeout("https://jsonplaceholder.typicode.com/users", 5000, "请求超时")
.then((data) => {
console.log(data);
})
.catch((error) => {
console.error(error.message);
});
大家如果对Promise.race
比较陌生,可以先用上面的demo
体验一下。想手写实现某些方法或框架的源码,前提一定是对原方法或原框架特别熟悉。
实现 Promise.race
方法的关键在于一点:
Promise
对象状态变为 fulfilled
或者 rejected
,它就会采用这个 Promise
对象的状态作为自己的状态,并返回它的结果或错误原因。基于这个思路,我们可以通过以下步骤来手写实现 Promise.race
方法:
Promise
对象数组。Promise
对象。Promise
对象数组,防止传入的对象数组中存在非Promise
元素,将所有遍历的元素都用Promise.resolve
包裹一下,保证处理的一定是Promise
对象。Promise
对象在执行中无论成功或失败,均直接返回。根据上述总结的思路,我们进行代码实现。
jsPromise.race = function (promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
Promise.resolve(promises[i]).then(resolve).catch(reject)
}
})
}
jsconst promise1 = new Promise(resolve => setTimeout(() => resolve('foo'), 3000));
const promise2 = new Promise(resolve => setTimeout(() => resolve('bar'), 2000));
const promise3 = new Promise((resolve, reject) => setTimeout(() => reject('baz'), 1000));
Promise.race([promise1, promise2, promise3])
.then(result => console.log(result))
.catch(error => console.error(error)); // 输出 "baz"
在本篇博客中,我们首先介绍了Promise.race
方法的使用场景,根据使用场景写了demo
示例体验了一下原生的Promise.race
,然后根据使用体验,分析了其实现原理,总结了手写实现的思路,最终我们手写实现了 Promise.race
方法,实现了该方法的核心思想,并提供了使用示例。
Promise.race
是一个非常实用的 Promise
方法,它可以让我们同时运行多个异步操作,并返回最先完成的操作的结果或错误原因。
本文作者:CreatorRay
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!