Разрешите обещания, созданные в Array.map по тайм-ауту

#javascript #node.js #arrays #es6-promise

Вопрос:

Я пытаюсь разрешить массив обещаний, используя тайм-аут, чтобы избежать исключений ограничения скорости для запросов 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);
  }
});
 

Комментарии:

1. Просто для уточнения, вы пытаетесь разделить выполнение каждого запроса на 5 секунд? т. Е. Сделайте первый запрос, подождите 5 секунд, сделайте второй запрос, подождите 5 секунд и так далее?

Ответ №1:

Если вы просто хотите потратить некоторое время между вызовами 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 , так как вы, вероятно, захотите проверить результат каждого запроса, прежде чем делать следующий. Например, если скорость третьего запроса будет ограничена, вам, вероятно, не стоит утруждать себя дальнейшими запросами.

Ответ №2:

Это потому 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,
          },
        },
      });
    });
 

Вы можете попробовать это: (это реакция, но вы должны сосредоточиться только на функции fetchData) и просмотреть журналы:
https://codesandbox.io/s/zen-feynman-ql833?file=/src/App.js