在超时时解决 Array.map 内创建的承诺
Resolve promises created within Array.map on a timeout
我正在尝试使用超时来解决一系列承诺,以避免 API 请求出现速率限制异常。但是,我仍然达到了速率限制,因为超时似乎不起作用。
不太确定如何进行这项工作。
router.route("/").put(async (req, res) => {
const { apiKey: access_token, course, assignments } = req.body;
try {
const returnedIds = [];
const promises = await assignments.map((assignment) => {
return axios({
method: "PUT",
url: `https://url.to.api/api/v1/courses/${course}/assignments/${assignment.id}`,
params: {
access_token,
},
data: {
assignment: {
points_possible: assignment.points_possible,
},
},
});
});
const promiseResolution = function() {
Promise.all([...promises]).then((values) => {
values.forEach((_, index) => {
returnedIds.push(assignments[index].id);
});
res.status(201).json({
returnedIds,
});
});
};
setTimeout(promiseResolution, 5000);
} catch (e) {
res.status(401);
}
});
这是因为 Promise.all
会立即触发所有承诺,所以您的 setTimeout
只是为所有承诺设置了超时,而不是为单个承诺设置超时。
您应该尝试延迟每个承诺:
const promises = await assignments.map((assignment) => {
// some delay function
return axios({
method: "PUT",
url: `https://url.to.api/api/v1/courses/${course}/assignments/${assignment.id}`,
params: {
access_token,
},
data: {
assignment: {
points_possible: assignment.points_possible,
},
},
});
});
您可以试试这个:(它是 React,但您应该只关注 fetchData 函数)并查看日志:
https://codesandbox.io/s/zen-feynman-ql833?file=/src/App.js
如果您只想在 API 次调用之间留出一些时间,这应该可以。
router.route("/").put(async (req, res) => {
const { apiKey, course, assignments } = req.body;
try {
const returnedIds = [];
for (const assignment of assignments) {
returnedIds.push(await loadID(apiKey, course, assignment));
await wait(5000);
}
res.status(201).json({ returnedIds })
} catch (e) {
res.status(401);
}
});
function wait(duration) {
return new Promise((resolve) => setTimeout(resolve, duration));
}
function loadID(apiKey, course, assignment) {
// Makes the request, parses out the stuff you want from the response...
}
我会警告不要使用 Promise.all
,因为您可能想在发出下一个请求之前检查每个请求的结果。例如,如果第三个请求受到速率限制,您可能不应该费心再提出请求。
我正在尝试使用超时来解决一系列承诺,以避免 API 请求出现速率限制异常。但是,我仍然达到了速率限制,因为超时似乎不起作用。
不太确定如何进行这项工作。
router.route("/").put(async (req, res) => {
const { apiKey: access_token, course, assignments } = req.body;
try {
const returnedIds = [];
const promises = await assignments.map((assignment) => {
return axios({
method: "PUT",
url: `https://url.to.api/api/v1/courses/${course}/assignments/${assignment.id}`,
params: {
access_token,
},
data: {
assignment: {
points_possible: assignment.points_possible,
},
},
});
});
const promiseResolution = function() {
Promise.all([...promises]).then((values) => {
values.forEach((_, index) => {
returnedIds.push(assignments[index].id);
});
res.status(201).json({
returnedIds,
});
});
};
setTimeout(promiseResolution, 5000);
} catch (e) {
res.status(401);
}
});
这是因为 Promise.all
会立即触发所有承诺,所以您的 setTimeout
只是为所有承诺设置了超时,而不是为单个承诺设置超时。
您应该尝试延迟每个承诺:
const promises = await assignments.map((assignment) => {
// some delay function
return axios({
method: "PUT",
url: `https://url.to.api/api/v1/courses/${course}/assignments/${assignment.id}`,
params: {
access_token,
},
data: {
assignment: {
points_possible: assignment.points_possible,
},
},
});
});
您可以试试这个:(它是 React,但您应该只关注 fetchData 函数)并查看日志: https://codesandbox.io/s/zen-feynman-ql833?file=/src/App.js
如果您只想在 API 次调用之间留出一些时间,这应该可以。
router.route("/").put(async (req, res) => {
const { apiKey, course, assignments } = req.body;
try {
const returnedIds = [];
for (const assignment of assignments) {
returnedIds.push(await loadID(apiKey, course, assignment));
await wait(5000);
}
res.status(201).json({ returnedIds })
} catch (e) {
res.status(401);
}
});
function wait(duration) {
return new Promise((resolve) => setTimeout(resolve, duration));
}
function loadID(apiKey, course, assignment) {
// Makes the request, parses out the stuff you want from the response...
}
我会警告不要使用 Promise.all
,因为您可能想在发出下一个请求之前检查每个请求的结果。例如,如果第三个请求受到速率限制,您可能不应该费心再提出请求。