如何 运行 每秒一个接一个地映射函数(异步、获取、承诺)而不是并行?

how to run map function (async, fetch, promise) every second one after another and not parallel?

我这里有一个地图功能,它应该从在线资源中获取数据。问题是,API 只允许每秒获取一次。所以我试着这样做:

const sleep = (ms: number) => {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
};

const promises = projectData.map(async (project, index) => {
        return await getAddress(asdf)
          .then((nominatimData) => {
        // ....do something...
          })
          .catch(async (e) => {
            console.log("failed", e);
            return await sleep(2000).then(() => {
              console.log("another try... ")
              return getAddress(asdf);
            });
          });
    });

    await Promise.allSettled(promises);

    console.log("Project Data", projectData); //does still fire before all getAddress() are present.. :(

有两个问题我想不通:

  1. map() 似乎并行完成它的工作(是真的吗?)这不是我想要的 - 因为就像我说的那样我需要它最好每秒一个接一个地工作

  2. 我的睡眠功能似乎根本不起作用。控制台日志一团糟,一切都在一次

使这项工作每秒一次的正确方法是什么?并且后备(只是运行“getAddress”)又可以吗?

非常感谢!

setTimeout() 是一个 ONCE 的函数,延迟到您指定的时间。 另一方面,setInterval() 是一个函数,它在无限循环中每秒(或每次您指定的时间)执行它内部的任何内容。

您可以在此处查看文档:setTimeout() and setInterval()

我要做的是将从 API 获取的函数包装在 setInterval() 中,像这样:

setInterval(() => {    
  your code here
}, 1000);

您可以随时更改这 1000 个(1000 毫秒或 1 秒)。

回答你的问题:

  1. 是的,map 不会等待 Promise 完成才能进行下一个操作,但是您可以使用 for 循环来解决这个问题。
  2. 因为你运行用map操作,你的sleep函数运行s一次并行处理数组中的每一项,逻辑很好,不是方法

您可以使用允许 async/await 操作的 for 循环,但是,由于您的目标是等待来自服务器的响应,我建议改用自定义游标循环

let cursor = 0;
const timeout = 1000;
const sleep = (ms) => {
    return new Promise((resolve) => {
        setTimeout(resolve, ms);
    });
};

const loop = async () => {
    // Break if index is out of bounds
    if (!projectData[cursor]) {
        return console.log('Done');
    }

    await getAddress(projectData[cursor]).then((nominatimData) => {
        // ....do something...
        // Proceed to the next element in the array
        cursor++;
        await loop();

    }).catch(async (e) => {
        console.log(`Failed, retrying in ${ timeout }ms`);
        await sleep(timeout);
        await loop(); // Retry the loop with the same cursor index
    });
};
await loop();