synapse-storage
Version:
Набор инструментов для управления состоянием и апи-запросами
64 lines (59 loc) • 2.49 kB
JavaScript
import { Observable } from "rxjs";
/**
* Конвертирует `RequestResponseModify` в Observable с поддержкой отмены запроса.
*
* **Зачем нужен:**
* `RequestResponseModify` — thenable-объект (имеет `.then()`), поэтому RxJS `from()`
* может конвертировать его в Observable напрямую. Однако при таком подходе теряется
* возможность отмены: когда RxJS отписывается от Observable (switchMap, takeUntil,
* unsubscribe), Promise продолжает висеть — HTTP-запрос не абортится.
*
* `fromRequest` создаёт Observable с teardown-функцией, которая вызывает `req.abort()`
* при отписке. Это гарантирует, что при переключении на новый запрос (switchMap)
* или остановке эффектов предыдущий HTTP-запрос будет реально отменён.
*
* Abort вызывается только если запрос ещё не завершился — при нормальном завершении
* (resolve/reject) teardown не абортит, чтобы не влиять на внутреннее состояние endpoint'а.
*
* @example
* ```ts
* import { fromRequest } from 'synapse-storage/reactive'
*
* // Вместо:
* from(getList.request({ limit: 20, offset: 0 }))
*
* // Используйте:
* fromRequest(getList.request({ limit: 20, offset: 0 }))
*
* // В эффекте с validateMap:
* apiCall: ([_action, _state, { pageSize }]) =>
* fromRequest(getList.request({ limit: pageSize, offset: 0 })).pipe(
* apiResult((data) => {
* dispatcher.dispatch.applyList(data)
* }),
* ),
* ```
*/ function fromRequest(req) {
return new Observable((subscriber)=>{
let settled = false;
req.wait().then((result)=>{
settled = true;
if (!subscriber.closed) {
subscriber.next(result);
subscriber.complete();
}
}).catch((err)=>{
settled = true;
if (!subscriber.closed) {
subscriber.error(err);
}
});
return ()=>{
if (!settled) {
req.abort();
}
};
});
}
export { fromRequest };
//# sourceMappingURL=fromRequest.js.map