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

目录

使用场景
基本使用
Promise.all实现思路
代码实现
核心源码
使用示例
总结

在之前的博文中,我们已经用ES6的类实现了一个Promise,提供了基础的then方法和catch方法,这是Promise最核心的内容。随着Promise不断的发展和业务场景的逐渐复杂,拓展了很多新的方法。比如我们这次要讲到的Promise.all

Promise.all 是一个 JavaScriptPromise对象 的内置静态方法,它可以接收一个由多个 promise 组成的数组或者其他可迭代对象,然后返回一个新的 promise。这个新的 promise 会在所有输入的 promise 都成功完成时,用一个包含所有完成值的数组来解决;或者在任何一个输入的 promise 失败时,用第一个失败原因来拒绝。Promise.all 可以用来并行执行多个异步任务,并且等待它们全部完成后再继续执行后续的代码。

使用场景

当你需要并行执行多个异步任务,并且等待它们全部完成后再继续执行后续的代码时,可以使用 Promise.all

例如,假设你需要从不同的 API 获取一些数据,然后将它们组合成一个结果来处理。

你可以使用 Promise.all 来同时发起多个网络请求,然后在所有请求都成功返回时,用一个包含所有响应数据的数组来处理 Promise.all 返回的 promise

如果任何一个请求失败,Promise.all 返回的 promise 就会被拒绝,你可以在 catch 语句中处理错误。

基本使用

我们以上述提到的使用场景,来对原生的Promise.all进行简单使用。

js
// 定义一个函数,用来发起网络请求 function fetch(url) { return new Promise((resolve, reject) => { // 使用 XMLHttpRequest 来模拟网络请求 let xhr = new XMLHttpRequest(); xhr.open("GET", url); xhr.onload = () => { if (xhr.status === 200) { // 如果请求成功,解析响应数据并解决 promise resolve(JSON.parse(xhr.response)); } else { // 如果请求失败,拒绝 promise 并传递错误信息 reject(new Error(xhr.statusText)); } }; xhr.onerror = () => { // 如果请求出错,拒绝 promise 并传递错误信息 reject(new Error("Network error")); }; xhr.send(); }); } // 定义一个数组,包含三个不同的 API 地址 let urls = [ "https://jsonplaceholder.typicode.com/users", "https://jsonplaceholder.typicode.com/posts", "https://jsonplaceholder.typicode.com/comments" ]; // 使用 Promise.all 来同时发起三个网络请求 Promise.all( urls.map(fetch) ) .then((results) => { // 当所有请求都成功返回时,results 是一个包含三个响应数据的数组 console.log(results); // 你可以在这里将 results 组合成一个结果进行处理 }) .catch((error) => { // 当任何一个请求失败时,error 是第一个失败原因 console.error(error); // 你可以在这里处理错误,例如显示一个提示信息或者重试请求 })

大家如果对Promise.all比较陌生,可以先用上面的demo体验一下。想手写实现某些方法或框架的源码,前提一定是对原方法或原框架特别熟悉。

Promise.all实现思路

实现 Promise.all 方法的关键在于:

  1. 在所有的 Promise 对象都成功时,返回一个包含所有 Promise 结果的数组。
  2. 如果有一个 Promise 对象失败,则立即返回失败原因。

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

  1. 传入一个 Promise 对象数组。
  2. 返回一个新的 Promise 对象。
  3. 创建一个空数组,用于存储每个 Promise 对象的结果。
  4. 遍历 Promise 对象数组,对于每个 Promise 对象,将它的结果添加到结果数组中。
  5. 如果有一个 Promise 对象失败,则将返回的 Promise 对象立即拒绝,并返回失败原因。
  6. 如果所有的 Promise 对象都成功,则返回包含所有结果的数组的 Promise 对象。

代码实现

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

核心源码

js
Promise.all = function (promises) { let results = []; let length = promises.length; let promiseCount = 0; return new Promise((resolve, reject) => { for (let i = 0; i < promises.length; i++) { Promise.resolve(promises[i]).then(res => { results[i] = res; promiseCount++; if (promiseCount === length) { resolve(results); } }, err => { reject(err); }) } }) }

使用示例

以下是使用手写的 Promise.all 方法的示例:

js
let promise1 = Promise.resolve(1); let promise2 = Promise.resolve(2); let promise3 = Promise.resolve(3); promise.all([promise1, promise2, promise3]) .then(results => { console.log(results); // [1, 2, 3] }) .catch(reason => { console.log(reason); });

总结

在本篇博客中,我们首先介绍了Promise.all方法的使用场景,根据使用场景写了demo示例体验了一下原生的Promise.all,然后根据使用体验,分析了其实现原理,总结了手写实现的思路,最终我们手写实现了 Promise.all 方法,实现了该方法的核心思想,并提供了使用示例。

手写实现一些核心的 JavaScript 方法可以帮助我们更好地理解这些方法的原理和工作方式,同时也可以提高我们的编程技能和代码能力。

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

本文作者:CreatorRay

本文链接:

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