Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to setTimeout on async await call node

How can I add a setTimeout to my async await function call?

I have

    request = await getProduct(productids[i]);

where

const getProduct = async productid => {
        return requestPromise(url + productid);
   };

I've tried

    request = await setTimeout((getProduct(productids[i])), 5000);

and got the error TypeError: "callback" argument must be a function which makes sense. The request is inside of a loop which is making me hit the rate limit on an api call.

exports.getProducts = async (req, res) => {
  let request;
  for (let i = 0; i <= productids.length - 1; i++) {
    request = await getProduct(productids[i]);
    //I want to wait 5 seconds before making another call in this loop!
  }
};
like image 265
jenryb Avatar asked Apr 29 '18 22:04

jenryb


People also ask

Can we use async await with setTimeout?

With the help of Node. js development team, we are now able to use async/await syntax while dealing with setTimeout() functions. This feature was initially implemented in Node v.

Is setTimeout asynchronous in Node js?

setTimeout() is an asynchronous function, meaning that the timer function will not pause execution of other functions in the functions stack.

Can you use setTimeout in Node?

The setTimeout function is used to call a function after the specified number of milliseconds. The delay of the called function begins after the remaining statements in the script have finished executing. The setTimeout function is found in the Timers module of Node. js.

Can I use async await in Node?

Async functions are available natively in Node and are denoted by the async keyword in their declaration. They always return a promise, even if you don't explicitly write them to do so. Also, the await keyword is only available inside async functions at the moment – it cannot be used in the global scope.


2 Answers

You can use a simple little function that returns a promise that resolves after a delay:

function delay(t, val) {
   return new Promise(function(resolve) {
       setTimeout(function() {
           resolve(val);
       }, t);
   });
}

And, then await that inside your loop:

exports.getProducts = async (req, res) => {
  let request;
  for (let id of productids) {
    request = await getProduct(id);
    await delay(5000);
  }
};

Note: I also switched your for loop to use for/of which is not required, but is a bit cleaner than what you had.

like image 73
jfriend00 Avatar answered Sep 30 '22 19:09

jfriend00


Actually, I have a pretty standard chunk of code that I use to do that:

function PromiseTimeout(delayms) {
    return new Promise(function (resolve, reject) {
        setTimeout(resolve, delayms);
    });
}

Usage:

await PromiseTimeout(1000);

If you're using Bluebird promises, then it's built in as Promise.timeout.

More to your problem: Have you checked API docs? Some APIs tell you how much you have to wait before next request. Or allow downloading data in larger bulk.

like image 22
Giulio Bambini Avatar answered Sep 30 '22 21:09

Giulio Bambini