вызов асинхронной функции внутри setTimeout

#javascript #node.js #express #es6-promise #asynchronous-javascript

#javascript #node.js #выразить #es6-обещание #асинхронный-javascript

Вопрос:

Я работаю над проектом, который построен с использованием express и node js. Мне просто нужно вызвать асинхронную функцию внутри функции setTimeout (обратный вызов)

Вот мой файл контроллера

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

Вот асинхронная функция в том же контроллере

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

Теперь я хочу спросить, в чем разница между этими двумя утверждениями

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

Я просто хочу вызвать функцию updateWhOrders параллельно перед отправкой ответа обратно в API.

Есть ли какая-либо конкретная причина для использования функции setTimeout? Или, если я опущу функцию setTimeout, она будет вести себя точно так же, как при использовании функции setTimeout?

Насколько я понимаю, если я опущу функцию setTimeout, она будет работать в фоновом режиме, возвращая обещание. Что, если я вызову функцию (updateWHOrders) внутри функции setTimeout. В чем выгода? Пожалуйста, поправьте меня, если я ошибаюсь.

Заранее благодарю вас 🙂

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

1. Использование setTimeout(func,0) просто приведет к тому, что узел пропустит эту строку на данный момент, запустите весь синхронный код, затем запустите func .

2. if I omit setTimeout function it will run in the background by returning a promise —> Нет, он все равно возвращает обещание (это async функция).

3. @JeremyThille. Он не обрабатывает функцию в фоновом режиме, возвращая обещание? поскольку асинхронная функция всегда возвращает обещание

4. Если я опущу setTimeout, то он не будет вызывать func позже, выполнив весь оставшийся код?

5. Что такое rows ? Это нигде не определено…

Ответ №1:

Вы не должны использовать setTimeout здесь: обратный вызов будет выполняться не параллельно, а позже, после выполнения остальной части синхронного кода.

Вместо этого, если это единственная асинхронная задача, которая должна выполняться перед вызовом res.status(200) , используйте await :

 await updateWhOrders(req.Orders, req);
 

Если у вас больше асинхронных задач, и они независимы друг от друга, так что они могут выполняться в любом порядке — и не нужно ждать результата другого — тогда используйте Promise.all :

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

Разница с setTimeout

Вы просили указать разницу между этими операторами:

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

Первая функция не будет вызываться updateWhOrders сейчас, но запланирует ее выполнение после выполнения всего синхронного кода. Это может быть сразу после выполнения следующего await , или, если его нет, после return выполнения. Сначала стек вызовов должен стать пустым и только после updateWhOrders этого может быть выполнен.

Второй будет выполнен updateWhOrders немедленно.

Ни один из них не использует тот факт, что updateWhOrders возвращает обещание, и поэтому этот аспект рассматривается недостаточно хорошо. Вы захотите узнать, когда асинхронный вызов внутри updateWhOrders завершит свою работу, и для этого вам нужно что-то сделать с возвращенным обещанием. Вот почему вы должны использовать либо .then , await , Promise.all , … , либо все, что связано с этим обещанием.

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

1. Спасибо. Но updateWHOrders — это независимая функция, которую необходимо вызывать, не блокируя остальную часть кода. Если я использую await, он выполнит его и будет ждать его завершения. Вместо этого я хочу выполнять параллельно, не дожидаясь его завершения

2. Итак, вы хотите res.status(200).json() , чтобы вас вернули до того, как это updateWHOrders будет вызвано? Вы уверены? Пожалуйста, объясните, с чем вы хотите, чтобы это было «параллельно»…

3. Нет. Я просто хочу завершить функцию updateWHOrders непосредственно перед res.status(200)

4. Если вы хотите updateWHOrders работать «параллельно» (в JS такого нет, но есть асинхронность) с другими асинхронными задачами , тогда выберите Promise.all версию и вызовите все другие асинхронные функции в том массиве, который передается ему в качестве аргумента, что является альтернативой, которую я ввел в свой ответ. Вам необходимо await убедиться, что все эти «параллельные» задачи завершены до return выполнения.

5. ОК. Спасибо. Но не могли бы вы, пожалуйста, рассказать мне о разнице между двумя синтаксисами функции updateWHOrders, которые я уже упоминал в постановке вопроса

Ответ №2:

Хассам. setTimeout основная функция заключается в вызове функции asynchronously . Он возвращает promise и является заменой new Promise функции в NodeJS. Отвечая на ваш вопрос, здесь вы не хотите updateWhOrders блокировать функцию и хотите запустить ее в отдельном потоке, не блокируя другую часть кода. Хотя NodeJS является однопоточным языком, он использует один и тот же поток для обработки синхронных и асинхронных вызовов, и они обрабатываются с помощью цикла событий. Чтобы узнать больше о цикле событий, вы можете посмотреть это видео: https://youtu.be/8aGhZQkoFbQ

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

1. Спасибо, но мне нужно больше информации