如何 运行 每秒一个接一个地映射函数(异步、获取、承诺)而不是并行?
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.. :(
有两个问题我想不通:
map() 似乎并行完成它的工作(是真的吗?)这不是我想要的 - 因为就像我说的那样我需要它最好每秒一个接一个地工作
我的睡眠功能似乎根本不起作用。控制台日志一团糟,一切都在一次
使这项工作每秒一次的正确方法是什么?并且后备(只是运行“getAddress”)又可以吗?
非常感谢!
setTimeout() 是一个 ONCE 的函数,延迟到您指定的时间。
另一方面,setInterval() 是一个函数,它在无限循环中每秒(或每次您指定的时间)执行它内部的任何内容。
您可以在此处查看文档:setTimeout() and setInterval()
我要做的是将从 API 获取的函数包装在 setInterval() 中,像这样:
setInterval(() => {
your code here
}, 1000);
您可以随时更改这 1000 个(1000 毫秒或 1 秒)。
回答你的问题:
- 是的,
map
不会等待 Promise 完成才能进行下一个操作,但是您可以使用 for
循环来解决这个问题。
- 因为你运行用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();
我这里有一个地图功能,它应该从在线资源中获取数据。问题是,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.. :(
有两个问题我想不通:
map() 似乎并行完成它的工作(是真的吗?)这不是我想要的 - 因为就像我说的那样我需要它最好每秒一个接一个地工作
我的睡眠功能似乎根本不起作用。控制台日志一团糟,一切都在一次
使这项工作每秒一次的正确方法是什么?并且后备(只是运行“getAddress”)又可以吗?
非常感谢!
setTimeout() 是一个 ONCE 的函数,延迟到您指定的时间。 另一方面,setInterval() 是一个函数,它在无限循环中每秒(或每次您指定的时间)执行它内部的任何内容。
您可以在此处查看文档:setTimeout() and setInterval()
我要做的是将从 API 获取的函数包装在 setInterval() 中,像这样:
setInterval(() => {
your code here
}, 1000);
您可以随时更改这 1000 个(1000 毫秒或 1 秒)。
回答你的问题:
- 是的,
map
不会等待 Promise 完成才能进行下一个操作,但是您可以使用for
循环来解决这个问题。 - 因为你运行用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();