Отмена асинхронных операций, cancellable callback and Promise в JavaScript

preview_player
Показать описание


#cancelable #asynchronous #асинхронность #async #просисы #nodejs #javascript #await #callback #колбек
Рекомендации по теме
Комментарии
Автор

1) неконсистентность результатов
Почему отмененный промис в случае успешности/неуспешности исходной операции возвращает различные результаты?
Было бы логичней, чтобы он в любом случае сообщал new Error('Cancelled'), скрывая тем самым исходную ошибку(которая нам не важна, ведь мы отменили этот промис)
2) ненужное ожидание выполнения исходной функции.
Пока она не выполнится(а это может занять много времени), мы не будем оповоещены что на самом деле промис ужа давным-давно отменен
логичней делать `reject(new Error('Cancelled'))` прямо в момент вызова .cancel()
так вызывающий код сразу узнает что действие отменено, а не по факту его завершения
При этом автоматически исправится первый недочет - ведь reject отмены, будучи вызванным первым уже установится промис в отклоненное состояние, и вызовы исходных resolve/reject уже не сыграют никакой роли

```
class Cancelable extends Promise {
static get [Symbol.species]() { return Promise; }// если хотим, чтобы при вызове then/catch/... создавались обычные Promise
constructor(executor) {
let _reject;
super((resolve, reject) => {
executor(resolve, reject);
_reject = reject;
});
this._reject = _reject;
this.canceled = false;
}

cancel() {
this.canceled = true;
this._reject(new Error('Cancelled'));
}
}
```

viktorgvozdev
Автор

Годится чисто для учебки, ибо на практике нужно кучу всего реализовать. Как минимум чейнинга нет.
Сancel не сработает если вызвать resolve/reject и в этом же тике с cancel, но до него. Т.е после вызова cancel ожидаем что then пойдет уже по reject ветке, но этого не будет, так как промис fulfilled и колбек then запланирован в микротаске. Как закрывать, если у промиса несколько then, что делать если суб-цепочка должна быть атомарная. Ну и куча других нюансов как написание плоского асинхронного кода с await/yield

IAmDigitalBrain
Автор

Вы сказали что `fetch` нельзя отменить, но как же `AbortSignal`?

БогданЮрчук-то
Автор

А так получится сделать реджект промису, и вместе с этим остоновить лоад дать процесс?


function loadData(url) {
let rejectPromise;
const dataPromise = new Promise((resolve, reject) => {
const data = new Data();
rejectPromise = reject;
data.load = () => { resolve(data) };
data.error = () => { resolve(null) };
data.url = url;
});
return {
promise: dataPromise,
cancel: () => {
rejectPromise();
}
}
}

vovasvidinsky
Автор

А что если вызывать `reject` промиса с ошибкой `Canceled` в методе `cancel`?

shtimn
Автор

cancel() {
this.canceled = true;
return this;
}

victorklimov