在之前的博文中,我们已经用
ES6
的类实现了一个Promise
,提供了基础的then
方法和catch
方法,这是Promise
最核心的内容。随着Promise
不断的发展和业务场景的逐渐复杂,拓展了很多新的方法。比如我们这次要讲到的Promise.all
。
Promise.all
是一个 JavaScript
中 Promise
对象 的内置静态方法,它可以接收一个由多个 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
对象都成功时,返回一个包含所有 Promise
结果的数组。Promise
对象失败,则立即返回失败原因。基于这个思路,我们可以通过以下步骤来手写实现 Promise.all
方法:
Promise
对象数组。Promise
对象。Promise
对象的结果。Promise
对象数组,对于每个 Promise
对象,将它的结果添加到结果数组中。Promise
对象失败,则将返回的 Promise
对象立即拒绝,并返回失败原因。Promise
对象都成功,则返回包含所有结果的数组的 Promise
对象。根据上述总结的思路,我们进行代码实现。
jsPromise.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
方法的示例:
jslet 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
方法可以帮助我们更好地理解这些方法的原理和工作方式,同时也可以提高我们的编程技能和代码能力。
本文作者:CreatorRay
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!