Как отложить вызов функции внутри экспресс-контроллера без зависания API? - PullRequest
0 голосов
/ 12 апреля 2019

Я учусь разрабатывать API ExpressJS, и мне нужно знать, как отложить вызов функции, но ответить клиенту кодом успеха, даже если процесс еще не завершен.

Простой пример кода:

router.post('/', (req,res) => {
   if(req.body.success) {
      createRecord(req.body); // I need this function to be called after X minutes
   }
   return res.status(201).send(`Record will be created in X min from ${now}.`)
});

При поиске нашел функцию setTimeout. Однако мне не ясно, как это работает.

  • Клиенту нужно подождать X минут, чтобы получить мое сообщение об успехе?
  • Функция createRecord вызывается, даже если функция уже вернула ответ?
  • API будет по-прежнему доступен для других вызовов в течение X минут?

Я надеюсь, что кто-то может помочь мне прояснить мои сомнения. Спасибо.

Ответы [ 4 ]

0 голосов
/ 12 апреля 2019
You can use setTimeout function once you get response and it will delay x minutes.     

    router.post('/', (req,res) => {
        if(req.body.success) {
        setTimeout(100, function(){

         createRecord(req.body); // I need this function to be called after X minutes
         });
        return res.status(201).send(`Record will be created in X min from ${now}.`)
       }

      });
0 голосов
/ 12 апреля 2019
// Step 1: Add a next to your function. It passes the context of your API call to another route handler. This enables you to pass the success message immediately and then do something else afterwards in your own time

 router.post('/', (req,res, next) => {
       if(req.body.success) {
       return res.status(201).send(`Record will be created in X min from ${now}.`);
    }
next(); // This sends the context of the original request to the next function underneath it.
    });

// Step 2: Function that promisifies the setTimeout function.
    const waitHere = (time) => new Promise(resolve => setTimeout(resolve, time));
setTimeout is an async function so it will wait

Step 2 - Option 1:
    router.use('/', async (req,res, next) => {
       if(req.body.success) {
    await waitHere(1000 * 60 *2); // 2 minute wait
          createRecord(req.body); 
    });
OR

Step 2 Option 2:
No need for the async since you're not doing anything else in the second function handler 
 router.use('/', (req,res) => {
       if(req.body.success) {
    setTimeout(() => {
 createRecord(req.body); 
}, 1000 * 60 * 2);

    });

API все еще будет доступен для других вызовов в течение X минут?- да, каждое выполнение API уникально.

Надеюсь, это поможет!

0 голосов
/ 12 апреля 2019

Если вы не знаете setTimeout, значит, вы не понимаете цикл обработки событий в JS. Вот разговор , который вы действительно должны смотреть!

А пока я кратко объясню основы.

Вы знаете, что когда вы вызываете функцию, она будет выполнять каждую строку кода в своем теле во временном порядке, до тех пор, пока не достигнет возврата, не выдаст ошибку или не достигнет последней строки.

Когда одна из строк является вызовом setTimeout(myDelayedFn, 1000), вызов самого setTimeout выполняется в порядке времени. Он отправляет запрос в среду выполнения, сообщая SCHEDULE о вызове myDelayedFn по крайней мере 1000 мс позже.

Не путайте термин request Я использовал здесь НЕ сетевой запрос. Вы можете думать об этом как о сигнале .

Поэтому setTimeout просто отправляет запрос на запланированную работу, но эта работа не выполняется. Выполнение myDelayedFn выпадает из-за нехватки времени, так как это ЗАПЛАНИРОВАНО. Это также означает, что ваш обычный построчный порядок выполнения не прерывается (мы говорим, что он не блокирует выполнение). После отправки запроса выполнение продолжается до следующей строки в теле функции.

Это означает «нет», «да», «да» на ваши 3 вопроса.

0 голосов
/ 12 апреля 2019

Для этого можно использовать функцию экспресс-промежуточного программного обеспечения

function delay (req, res, next) {
  setTimeout(function(){
    console.log("delay occurred");  //do the task you want to do
        if(true) {
  console.log("record created after 3 seconds"); // I need this function to be called after X minutes
}


},3000)
}

      // you can return response here ,so that cliet does'nt have to wait
    router.post('/', function(req, res, next) {

                  return res.status(201).send(`Record will be created in X min from ${now}.`)
                  next(); // call next here
                },delay);
...