Обслуживает ли koa отмененные запросы?

У меня есть конечная точка в koa, которая загружает много данных из базы данных, а затем вычисляет некоторые результаты на их основе. Это может занять несколько секунд.

Что происходит с запросом, если браузер отменяет его? Например, вкладка браузера закрывается и т. Д.

Например, будет ли cache.c заполнено, даже если браузер отменит или достаточно умен, чтобы просто остановить любые действия, которые он начал для этого запроса?

const cache = {}
router.get('/data', function *(next) {

  if (cache.c) return this.body = cache.c

  // somewhere here the browser cancels the request
  //---
  const a = yield db.getA()
  const b = yield db.getB()
  cache.c = yield calculateC(a,b)
  //---

  this.body = cache.c

})

person K..    schedule 15.12.2015    source источник


Ответы (1)


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

Остановка дальнейшего выполнения генератора только потому, что сокет закрывается, не является предположением, которое может сделать Koa.

Например, представьте, что Koa автоматически остановил выполнение генератора, и пользователь закрывает сокет до того, как yield query('ROLLBACK') получит возможность очистить соединение с базой данных. Теперь у вас есть неудачное соединение с базой данных, застрявшее в пуле. Может быть, есть даже более весомые причины, чем это.

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

Если вы хотите знать, когда пользователь закрыл вкладку, чтобы вы могли реализовать собственное поведение короткого замыкания, вы можете прослушивать событие "close" в сокете запроса:

const cache = {}
router.get('/data', function *(next) {
  if (cache.c) return this.body = cache.c;

  var closed = false;
  this.request.socket.on('close', function() {
    closed = true;
  });

  if (closed) return;
  const a = yield db.getA();
  if (closed) return;
  const b = yield db.getB();
  if (closed) return;
  cache.c = yield calculateC(a,b);

  this.body = cache.c;
})
person danneu    schedule 20.12.2015
comment
Полезно знать :) Моя идея заключалась в том, чтобы сохранить результаты длительных вычислений, чтобы пользователь мог их восстановить, если они вернутся. - person K..; 21.12.2015
comment
В этом случае вы можете просто рассмотреть шаблон фоновой обработки. В маршруте вставьте незавершенное задание в таблицу заданий. В фоновой очереди, в задании cron, в цикле setInterval или даже сразу после того, как вы вернули ответ пользователю, обработайте задания и установите их статус как завершенный. Когда пользователь проверяет свою страницу, вы можете отобразить все еще обрабатываемые или результат задачи. Тогда вам не нужно заставлять пользователя синхронно ждать завершения вычислений, и вы можете сделать это независимо от того, закрыли ли они вкладку. - person danneu; 22.12.2015