编辑
2023-06-27
手写源码系列
00
请注意,本文编写于 360 天前,最后修改于 331 天前,其中某些信息可能已经过时。

目录

使用场景
Promise.race实现思路
代码实现
核心代码
使用示例
总结

Promise.racePromise.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 APIsetTimeout来实现超时机制的代码示例

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.race 方法的关键在于一点:

  • 传入的任意一个 Promise 对象状态变为 fulfilled 或者 rejected,它就会采用这个 Promise 对象的状态作为自己的状态,并返回它的结果或错误原因。

基于这个思路,我们可以通过以下步骤来手写实现 Promise.race 方法:

  • 传入一个 Promise 对象数组。
  • 返回一个新的 Promise 对象。
  • 遍历 Promise 对象数组,防止传入的对象数组中存在非Promise元素,将所有遍历的元素都用Promise.resolve包裹一下,保证处理的一定是Promise对象。
  • 任意Promise对象在执行中无论成功或失败,均直接返回。

代码实现

根据上述总结的思路,我们进行代码实现。

核心代码

js
Promise.race = function (promises) { return new Promise((resolve, reject) => { for (let i = 0; i < promises.length; i++) { Promise.resolve(promises[i]).then(resolve).catch(reject) } }) }

使用示例

js
const 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 方法,它可以让我们同时运行多个异步操作,并返回最先完成的操作的结果或错误原因。

如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:CreatorRay

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!