在超时时解决 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,因为您可能想在发出下一个请求之前检查每个请求的结果。例如,如果第三个请求受到速率限制,您可能不应该费心再提出请求。