使用 Promise.all 同时解析时每个 Promise 的线性时间增加?

问题描述 投票:0回答:1

我有一个方法可以逐步执行 JSON 有效负载以对该有效负载中的某些数据运行计算。当我创建该方法的 100 个 Promise,然后将它们传递给 Promise.all() 时,似乎对于同时解决的每个 Promise,下一个需要更长的时间才能解决。

这不是我的方法所特有的,我已经尝试使用返回简单 JSON 数据的公共 API 进行类似的操作。在使用 Promise.all 同时调用该 API 时,我观察到了同样的事情......每个连续的 Promise 都需要越来越长的时间才能解决。

这是一个简单的代码片段来说明我在做什么:

const axios = require('axios');

const getSomeData = async () => {
  try {
    await axios.get('https://some.api.com');
  } catch (error) {
    console.log('Failed to get data...');
  }
};

const promiseList = [];

for (let i = 0; i < 100; i += 1) {
  promiseList.push(new Promise(async (res) => {
    const startTime = performance.now();
    await getSomeData();
    const stopTime = performance.now();
    console.log(`time taken by promise: ${stopTime - startTime}`);
    res();
  }));
}

const main = async () => {
  const startTime = performance.now();
  await Promise.all(promiseList);
  const stopTime = performance.now();
  console.log(`total time taken: ${stopTime - startTime}`);
};

main();

这当然是一个毫无意义的方法,但我创建它是为了严格观察并发运行时 Promise 的行为方式,以及与顺序运行相比有多少性能优势(这显然是一个重大改进)。

我的问题是,什么会导致每个连续的承诺需要越来越长的时间才能解决所有承诺?在这种情况下,如果我再次运行它,它会将第一个 Promise 所需的时间重置为大约 200 毫秒,然后再次开始增加,直到最后一个 Promise 需要大约 600 毫秒才能解决。

这只是单线程 Javascript 执行和并发的本质吗?我真的很想听到对这种现象的更深入的解释。

javascript async-await promise parallel-processing promise.all
1个回答
0
投票

检查网络瀑布:

我猜你的 api 调用只是在后端受到限制。您的请求也在后端排队。

如果您用超时替换 api 调用,

Promise.all
工作得很好:

const getSomeData = () => {
  try {
    return new Promise(r => setTimeout(r, 1000))
  } catch (error) {
    console.log('Failed to get data...');
  }
};

const promiseList = [];
const log = [];

for (let i = 0; i < 100; i += 1) {
  promiseList.push(new Promise(async (res) => {
    const startTime = performance.now();
    await getSomeData();
    const stopTime = performance.now();
    log.push(`time taken by promise: ${stopTime - startTime}`);
    res();
  }));
}

const main = async () => {
  const startTime = performance.now();
  await Promise.all(promiseList);
  const stopTime = performance.now();
  log.forEach(l => console.log(l));
  console.log(`total time taken: ${stopTime - startTime}`);
};

main();

© www.soinside.com 2019 - 2024. All rights reserved.