Прекратить выполнение задачи после тайм-аута запроса в Express.js - PullRequest
0 голосов
/ 07 февраля 2019

Давайте предположим, что у нас есть код ниже, для которого установлено время ожидания на 5 секунд.

router.get('/timeout', async (req, res, next) => {
      req.setTimeout(5000, () => {
        res.status(503)
        res.send()
      })
      while (true) {
        console.log("I'm alive")
      }
      res.status(200)
      res.send({msg: 'success'})
})

Я знаю, что две последние строки никогда не будут достигнуты, но это не точка.Проблема, которую я хочу решить, заключается в том, что цикл while все еще работает, несмотря на то, что ответ был отправлен.

Есть ли способ убить такие еще работающие задачи?

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

Существует два типа долгосрочных задач, и отмена для обоих различна:

1) Асинхронные задачи:

Они могут занять некоторое время, однако они не используют движок JavaScript,вместо этого движок находится в режиме ожидания, ожидая каких-то внешних данных (базы данных / файлов / таймеров и т. д.).В некоторых случаях (например, таймеры) вы можете легко отменить это внешнее действие, а также вызвать его как событие, так как двигатель не заблокирован и может обработать отмену.Если асинхронное действие не может быть отменено напрямую (например, чтение базы данных), вы можете подождать, пока оно не будет выполнено, и отменить его:

 class Cancelable {
   constructor() { 
     this.cancelled = false;
     this.handlers = [];
   }

   onCancel(handler) { this.handlers.push(handler); }

   cancel() {
     this.cancelled = true;
     this.handlers.forEach(handler => handler());
   }
}


// inside of the request handler:
const canceller = new Cancelable;

req.setTimeout(5000, () => {
    res.status(503);
    res.send();
    canceller.cancel(); // propagate cancellation
});

// Some long running, async cancellable task
const timer = setTimeout(function() {
  res.send("done");
}, 10000 * Math.random())

// on cancellation just remove the timer
canceller.onCancel(() => clearTimeout(timer));

unCancellableAction(function callback() {
  if(canceller.canceled) return; // exit early if it was cancelled
  res.send("done");
});

2) Синхронные задачи: вы не можете отменить синхронные задачи напрямую, так как механизм работает.занят выполнением задачи и не может справиться с отменой.Чтобы сделать их отменяемыми, необходимо использовать опрос, задача должна приостановить свою работу, проверить, следует ли ее отменить, а затем продолжить или прервать.В JS это можно сделать с помощью функций генератора (поскольку они могут привести к их выполнению):

function runMax(time, action) {
  const gen = action(), start = Date.now();
  let done, value;
  do {
   ({ done, value } = gen.next());
  } while(!done && Date.now() < start + time)
  return value;
}

// inside the request handler:
runMax(5000, function* () {
  while(true) {
   // ... some jobs
   // yield at a safe position to allow abortion:
   yield;
  }
});
0 голосов
/ 07 февраля 2019

Я думаю, вам нужно добавить в цикл while новый оператор if, чтобы разорвать цикл.

Например:

while (!req.timeout) {
    if (!req.timeout) {
        break;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...