javascriptnode.jsexpresses6-promiseasynchronous-javascript

call Async function inside setTimeout


I am working on a project which is built using express and node js. I just need to call the async function inside the SetTimeout function (callback)

Here is my Controller File

module.exports.create = async (req, res) => {
  try {
    // Some DB Calls

    setTimeout(() => updateWhOrders(req.Orders, req), 0)

    // Some DB Calls

    return res.status(200).json({ data , msg: "record created successfully", success: true })
  } catch (error) {
    if (error?.message?.includes("Validation error")) {
      return handleErr({ message: "This supplier order id has already been added. Please refresh the page and check further down the screen." }, res)
    }
    return handleErr(error, res)
  }
}

Here is the async function in the same controller

const updateWhOrders = async (allOrders, req) => {
  // Some DB Calls using async await
  await SourceOrder.bulkCreate(allOrders.data, { updateOnDuplicate: ["wh_address"] })
}

Now I want to ask the difference between these two statements

1. setTimeout(() => updateWhOrders(req.Orders, req), 0)
2. updateWhOrders(req.Orders, req)

I just want to call the updateWhOrders function parallel before sending the response back to the API.

Is there any specific reason to use the setTimeout function? Or if I omit the setTimeout function it will behave exactly the same as using setTimeout function?

According to my understanding if I omit setTimeout function it will run in the background by returning a promise. What if I call function(updateWHOrders) inside setTimeout function. What is the benefit? Please correct me if I am wrong.

Thank you in Advance :)


Solution

  • You shouldn't use setTimeout here: it will not execute the callback in parallel, but later, after the rest of the synchronous code has executed.

    Instead, if it is the only asynchronous task that needs to happen before the call of res.status(200), then use await:

    await updateWhOrders(req.Orders, req);
    

    If you have more asynchronous tasks, and they are independent of each other such that they could execute in any order -- and don't have to wait for the other's result -- then use Promise.all:

    await Promise.all([
        updateWhOrders(req.Orders, req),
        anotherAsyncFunc(),
        yetAnotherAsyncFunc()
    ]);
    

    Difference with setTimeout

    You asked for the difference between these statements:

    setTimeout(() => updateWhOrders(req.Orders, req), 0)
    updateWhOrders(req.Orders, req)
    

    The first will not call updateWhOrders now, but will schedule it for execution after all synchronous code has executed. This could be just after the next await has executed, or if there is none, after the return has executed. The call stack must become empty first and only then updateWhOrders can get executed.

    The second will execute updateWhOrders immediately.

    Neither use the fact that updateWhOrders returns a promise, and so this aspect is not well dealt with. You'll want to know when the asynchronous call inside updateWhOrders has finished its job, and for that you need to do something with the returned promise. That's why you should use either .then, await, Promise.all, ...or anything that deals with that promise.