コンテンツにスキップ

fromAbortablePromise

AbortSignal を受け取る Promise のファクトリから Observable を作成します。Observable が complete すると(たとえば switchMap が新しい内側の Observable に切り替えたとき)、AbortController が自動で abort され、実行中のリクエストが取り消されます。

Promise が解決されると Result.ok(value) を、拒否されると Result.err(error) を発行します。abort による拒否(AbortError)は無視され、何も発行しません。

// Timeline:
//
// query$ "a" "b"
// request a [in flight] | (aborted)
// request b [in flight] -> "result for b"
// results$ Ok("result for b")
//
// Explanation:
// - fromAbortablePromise hands its factory an AbortSignal
// - switchMap completes the previous inner observable, which aborts it
// - The AbortError that follows is swallowed, so nothing is emitted for it
const search = (query: string, signal: AbortSignal): Promise<string> =>
new Promise((resolve, reject) => {
const timer = setTimeout(() => {
resolve(`result for ${query}`);
}, 50);
signal.addEventListener('abort', () => {
clearTimeout(timer);
reject(new DOMException('aborted', 'AbortError'));
});
});
const query$ = source<string>();
const results$ = query$.pipe(
switchMap((query) =>
fromAbortablePromise((signal) => search(query, signal)),
),
);
const valueHistory: Result<string, unknown>[] = [];
results$.subscribe((result) => {
valueHistory.push(result);
});
query$.next('a');
query$.next('b');
await new Promise<void>((resolve) => {
setTimeout(resolve, 150);
});
assert.deepStrictEqual(valueHistory, [Result.ok('result for b')]);

取り消せるリクエストには、fromPromise の代わりにこちらを使ってください。典型的には switchMap の射影関数の中で使い、誰も答えを待たなくなったリクエストを走らせたままにせず abort します。

View source on GitHub