Forma adequada para Abortar (parar) execução de async/await função?

0

Pergunta

Houve outros temas em SI, mas a maioria deles são datados de há 5 anos atrás. O que é a actual, up-to-date abordagem para cancelar aguardam chamada em JS? i.e.

async myFunc(){
    let response = await oneHourLastingFunction();
    myProcessData(response);
}

em determinado momento da aplicação decide que não quer mais esperar oneHourLastingFunction, mas ele está preso no "esperam". Como cancelar isso? De qualquer padrão de maneiras de cancelamento-de tokens/abortControllers de promessas?

1

Melhor resposta

1

Cancelamento de um procedimento assíncrono ainda não é uma tarefa trivial, especialmente quando você precisa de um profundo cancelamento e controle de fluxo. Não há uma solução nativa, no momento. Tudo o que você pode fazer nativamente:

  • passar AbortController instância para cada aninhadas assíncrono função que você deseja fazer cancelável
  • subscrever todos os internos do micro-tarefas (pedidos, temporizadores, etc) para o sinal
  • opcionalmente cancelar concluída micro-tarefas do sinal
  • chamada abort método do controlador para cancelar todos os inscritos micro-tarefas

Isso é muito extenso e complicado uma solução com potencial de vazamentos de memória.

Eu posso apenas sugerir a minha própria solução para este desafio- c-promise2, que fornece cancelável promessas e um cancelável alternativa para a ECMA funções assíncronas - geradores.

Aqui está um exemplo básico (Demonstração ao Vivo):

import { CPromise } from "c-promise2";

// deeply cancelable generator-based asynchronous function
const oneHourLastingFunction = CPromise.promisify(function* () {
  // optionally just for logging
  this.onCancel(() =>
    console.log("oneHourLastingFunction::Cancel signal received")
  );
  yield CPromise.delay(5000); // this task will be cancelled on external timeout
  return "myData";
});

async function nativeAsyncFn() {
  await CPromise.delay(5000);
}

async function myFunc() {
  let response;
  try {
    response = await oneHourLastingFunction().timeout(2000);
  } catch (err) {
    if (!CPromise.isCanceledError(err)) throw err;
    console.warn("oneHourLastingFunction::timeout", err.code); // 'E_REASON_TIMEOUT'
  }
  await nativeAsyncFn(response);
}

const nativePromise = myFunc();

Profundamente anuláveis solução (todas as funções são anuláveis) (Demonstração ao Vivo):

import { CPromise } from "c-promise2";

// deeply cancelable generator-based asynchronous function
const oneHourLastingFunction = CPromise.promisify(function* () {
  yield CPromise.delay(5000);
  return "myData";
});

const otherAsyncFn = CPromise.promisify(function* () {
  yield CPromise.delay(5000);
});

const myFunc = CPromise.promisify(function* () {
  let response;
  try {
    response = yield oneHourLastingFunction().timeout(2000);
  } catch (err) {
    if (err.code !== "E_REASON_TIMEOUT") throw err;
    console.log("oneHourLastingFunction::timeout");
  }
  yield otherAsyncFn(response);
});

const cancellablePromise = myFunc().then(
  (result) => console.log(`Done: ${result}`),
  (err) => console.warn(`Failed: ${err}`)
);

setTimeout(() => {
  console.log("send external cancel signal");
  cancellablePromise.cancel();
}, 4000);
2021-11-25 16:48:29

Em outros idiomas

Esta página está em outros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................