【问题标题】:Promise inside for loop with setTimeout带有 setTimeout 的 for 循环内的 Promise
【发布时间】:2020-06-13 17:43:12
【问题描述】:

我有如下代码。我打算做的是:
1) For 循环并按顺序调用 api。
2) 下一个 for 循环迭代仅在 promise resolve 后执行,延迟 1 秒。

我正在这样做,但 console.log 什么也没打印。处理它的正确方法是什么?

const axios = require('axios');

function getData(i){
    return axios.get(`http://www.api.com/${i}`);
}

for (let i = 0; i < 10000000; i++) {
    setTimeout(() => {
        getData(i)
            .then((res) => {
                console.log(`successs ${i}`);
            })
            .catch((err) => {
                console.log(`fail ${i}`);
            })
    }, 1000)
}

【问题讨论】:

  • 所以你真的想开始延迟1秒,甚至在请求之前?
  • 这将在 1 秒内触发 all 承诺获取(嗯,等待能够运行)。请参阅“promise chaining”,了解如何将其调整为按序列运行。最直接的转换是仅从先​​前承诺的解决中调用“setTimeout”。使用一个函数,这样就可以递归地完成。
  • 现在,对于“不记录”位。 1.尝试登录getData(以显示promise确实创建了); 2. 将循环更改为仅 1..10 (以避免创建过多的计时器和承诺的并发症)。

标签: javascript node.js ecmascript-6


【解决方案1】:

您的代码基本上会在 1 秒延迟后同时运行 10000000 个 api 请求。您需要链接 API 调用,以便它们一个接一个地运行:

    const axios = require('axios');

    function getData(i){
        return axios.get(`http://www.api.com/${i}`);
    }

    function wait(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    function dataLoop() {
       const getOne = (i: number) => {
         if (i < 10000000) {
            getData(i)
                .then((res) => {
                    console.log(`successs ${i}`);
                })
                .catch((err) => {
                    console.log(`fail ${i}`);
                })
                .then(wait(1000))
                .then(() => getOne(i + 1))
         }
       }
       getOne(0);
    }
    dataLoop();

如果可能的话,我建议在您的情况下尝试使用 async/await,它可以大大简化事情。

for (let i = 0; i < 10000000; i++) {
    try {
        const res = await getData(i);
        console.log(`successs ${i}`);
    } catch (e) {
        console.log(`fail ${i}`);
    }
    await wait(1000);
}

【讨论】:

  • 哇,与 promise 相比,异步等待的代码看起来非常干净。我会试试看:D
  • @stackdisplay - 请记住async/await 完全基于承诺,没有承诺就没有任何用处。所以,这不是async/await 与承诺。这是使用带有承诺的async/await 与普通承诺。 async/await 版本之所以有效,是因为 getData() 返回一个连接到异步操作的承诺。
  • 有没有没有递归调用和没有async/await的解决方案? b/c async 重现相同的流程;它在得到结果之前就结束了。
猜你喜欢
  • 1970-01-01
  • 2019-08-21
  • 1970-01-01
  • 1970-01-01
  • 2010-12-19
  • 1970-01-01
  • 1970-01-01
  • 2013-10-08
相关资源
最近更新 更多