Search code examples
javascriptnode.jsarrayses6-promise

Resolve promises created within Array.map on a timeout


I'm trying to resolve an array of promises using a timeout to avoid rate limit exceptions on API requests. However, I'm still hitting the rate limit, as the timeout doesn't seem to be working.

Not really sure how to make this work.

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);
  }
});

Solution

  • If you just want to put some time between API calls this should do.

    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...
    }
    

    I would caution against using Promise.all since you probably want to check the result of each request before making the next one. For example, if the third request gets rate limited, you probably shouldn't bother making further requests.