最近有同学面试时被问到,如果并行执行多个异步操作,该如何操作。
这个问题很简单,当然可以使用
Promise.all()
的静态方法。
Promise.all()
会并行执行多个异步操作时等待所有操作完成,并在所有操作完成后返回结果。
基本操作如下(该代码在React环境下运行)
import axios from 'axios';
import { useEffect } from 'react';
export default function TestPromise() {
let executePromiseAll = async () => {
let pending = [];
for (let i = 1; i <= 10; i++) {
pending.push(axios.get("/api/users/get/" + i));
Promise.all(pending).then(res => {
console.log(res);
useEffect(() => {
executePromiseAll();
},[])
return (
测试promise.all
</div>
但是面试官继续发问,如何自己去实现一个Promise.all()
函数呢?这个时候同学就卡壳了...一问到稍微底层的就有点虚,加上面试紧张,很容易不知道该从何说起。
其实这个问题要实现很简单,
首先你要知道Promise无非就三种状态,pending,fulfilled和rejected
Promise.all()
需要的参数是一个全部是pending
状态promise数组,最后Promise.all()
执行,将所有结果返回成一个数组。如果有一个失败,则全部失败。
那问题就很简单了啊,如果我们自己实现Promise.all()
的话,只需要写一个函数,传一个全部pending状态的数组,迭代数组中的每个元素并执行,将返回结果放入到数组中即可。
let promiseAll = (promises) => {
return new Promise((resolve, reject) => {
if (promises.length === 0) {
resolve([]);
return;
let result = [];
let count = 0;
promises.forEach((promise, index) => {
Promise.resolve(promise).then((value) => {
result[index] = value;
count++;
if (count === promises.length) {
resolve(result);
}).catch((error) => {
reject(error);
这个自定义的函数用起来,和Promise.all()
就是一模一样的
promiseAll(pending).then(res => {
console.log(res);
这个实现实际上是很简单的,但是由此我想到了另外一个比较复杂的面试题的:
要求写一个函数,传入一个url地址的数组和number值,能够根据number值实现并发执行的效果,并将执行的结果放入到一个数组中
首先你要读懂题意,简单来说,比如有10个同时执行的异步操作,执行这个函数,传入的number值如果是3,那么就3个一组,3个一组的执行异步操作。类似于下面的效果:
要完成这个题目,首先要知道,明白一个道理,比如_request()
是一个异步执行函数,如果我们连续执行三次_request()
,是一个什么结果
_request();
_request();
_request();
如图,3个异步操作,调用的是一个接口,只是传递的值一样,这样,你看到的效果其实接近于同步效果。那也就是说,如果我们像这样同时调用异步函数,无论你怎么调用,都达不到上面的那种效果。
但是,如果在异步调用函数里面,当执行完结果后,再次执行自身递归,那就可以达到先执行完一个异步,再执行下一个的目的。伪代码如下:
async function _request(){
let resp = await axios.get('xxx');
_request();
大家都知道await是语法糖,所以,放在await后面的,肯定是当前异步函数执行之后的操作,因此,如果_request()
是像上面的递归函数,那么执行的效果,就如下图:
了解这个重点之后,就可以直接上代码了
* 并发请求
* @param {Array} urls 请求的url数组
* @param {Number} max 同时并发的数量,默认值3
* @returns {Array} result 并发请求后,返回所有请求的结果
let concurrency = (urls, max=3) => {
return new Promise((resolve, reject) => {
if (urls.length === 0) {
resolve([]);
return;
let result = [];
let count = 0;
let index = 0;
async function _request() {
if (index === urls.length) {
return;
let i = index;
let url = urls[index];
index++;
console.log(url);
try {
let res = await axios.get(url);
result[i] = res;
} catch (e) {
result[i] = e;
} finally {
count++;
if (count === urls.length) {
console.log('请求全部执行完毕');
resolve(result);
_request();
let times = Math.min(max, urls.length);
for (let i = 0; i < times; i++) {
_request();
调用并发:
let urls = [];
for (let i = 1; i <= 10; i++) {
urls.push("/api/users/get/" + i);
concurrency(urls, 3).then(resp=>console.log(resp));
完整案例:
import axios from 'axios';
import { useEffect } from 'react';
export default function TestPromise() {
let executePromiseAll = async () => {
let urls = [];
for (let i = 1; i <= 10; i++) {
urls.push("/api/users/get/" + i);
concurrency(urls, 3).then(resp=>console.log(resp));
let promiseAll = (promises) => {
return new Promise((resolve, reject) => {
if (promises.length === 0) {
resolve([]);
return;
let result = [];
let count = 0;
promises.forEach((promise, index) => {
Promise.resolve(promise).then((value) => {
result[index] = value;
count++;
if (count === promises.length) {
resolve(result);
}).catch((error) => {
reject(error);
* 并发请求
* @param {Array} urls 请求的url数组
* @param {Number} max 同时并发的数量,默认值3
* @returns {Array} result 并发请求后,返回所有请求的结果
let concurrency = (urls, max=3) => {
return new Promise((resolve, reject) => {
if (urls.length === 0) {
resolve([]);
return;
let result = [];
let count = 0;
let index = 0;
async function _request() {
if (index === urls.length) {
return;
let i = index;
let url = urls[index];
index++;
console.log(url);
try {
let res = await axios.get(url);
result[i] = res;
} catch (e) {
result[i] = e;
} finally {
count++;
if (count === urls.length) {
console.log('请求全部执行完毕');
resolve(result);
_request();
let times = Math.min(max, urls.length);
for (let i = 0; i < times; i++) {
_request();
useEffect(() => {
executePromiseAll();
},[])
return (
测试promise.all
</div>
本文链接:http://www.yanhongzhi.com/post/promise_all.html
-- EOF --
admin
2023-04-24 23:51:44
,添加在分类
JavaScript进阶
,并被添加「
JavaScript
,最后修改于
2023-04-24 23:51:44