Как правильно отменить http-запрос в Node.js? - PullRequest
8 голосов
/ 11 июня 2019

Мне нужно реализовать отменяемый клиентский HTTP-запрос в Node.js без использования внешних библиотек.Я даю объект Promise - cancellationPromise - который отклоняется при внешнем запросе отмены.Вот откуда я знаю, что мне, возможно, потребуется позвонить request.abort().

Вопрос в том, должен ли я звонить request.abort() только в том случае, если https.request все еще находится на рассмотрении, а response объект еще не доступен?

Или, еслиЯ буду вызывать его, даже если я уже получил объект response и обрабатываю данные ответа, как в коде ниже?В этом случае это остановит больше response.on('data') событий от прихода?

  async simpleHttpRequest(url, oauthToken, cancellationPromise) {
    let cancelled = null;
    let oncancel = null;

    cancellationPromise.catch(error => { 
      cancelled = error; oncancel && oncancel(error) });

    try {
      const response = await new Promise((resolve, reject) => {
        const request = https.request(
          url.toString(), 
          { 
            method: 'GET', 
            headers: { 'Authorization': `Bearer ${oauthToken}` }        
          }, 
          resolve);

        oncancel = error => request.abort();
        request.on('error', reject);
        request.end();
      });

      if (cancelled) throw cancelled;

      // do I need "oncancel = null" here?
      // or should I still allow to call request.abort() while fetching the response's data?

      // oncancel = null;

      try {
        // read the response 
        const chunks = await new Promise((resolve, reject) => {
          response.on('error', reject);  
          const chunks = [];
          response.on('data', data => chunks.push(data));
          response.on('end', () => resolve(chunks));
        });

        if (cancelled) throw cancelled;
        const data = JSON.parse(chunks.join(''));
        return data;
      }
      finally {
        response.resume();
      }
    }
    finally {
      oncancel = null;
    }
  }

1 Ответ

6 голосов
/ 18 июня 2019

Это зависит от того, чего вы хотите добиться, отменив запрос.

Просто немного фона. HTTP 1 не может «отменить» запрос, который он отправляет, а затем ждет ответа. Вы не можете "откатить" сделанный вами запрос. Для этого вам нужна распределенная транзакция. ( Дальнейшее чтение. ) Как указано в документе разработчика MDN :

Метод XMLHttpRequest.abort () прерывает запрос, если он уже был отправлен. Когда запрос прерывается, его readyState изменяется на XMLHttpRequest.UNSENT (0), а код состояния запроса устанавливается на 0.

По сути, вы останавливаете обработку ответа вашим приложением. Другое приложение, вероятно, (если вы позвонили abort() после того, как оно было ему отправлено) в любом случае завершит свою обработку.

С точки зрения вопроса:

Вопрос в том, должен ли я звонить request.abort() только в том случае, если https.request еще ожидает ответа, а объект ответа еще не доступен?

TL.DR .: Это имеет значение только с точки зрения вашей заявки. Когда я смотрю на ваш код, думаю, он будет работать нормально.

...