Skip to content

Commit 758ed20

Browse files
committed
Polyfill AbortSignal.any and AbortSignal.timeout for React Native
1 parent 903f861 commit 758ed20

1 file changed

Lines changed: 41 additions & 0 deletions

File tree

packages/common/src/Task.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,32 @@ const isAbortError = (error: unknown): error is AbortError =>
216216
error !== null &&
217217
(error as { type?: unknown }).type === "AbortError";
218218

219+
// For React Native
220+
if (typeof AbortSignal.any !== "function") {
221+
AbortSignal.any = function (signals: Array<AbortSignal>): AbortSignal {
222+
const controller = new AbortController();
223+
224+
const onAbort = (event: Event) => {
225+
controller.abort((event.target as AbortSignal).reason);
226+
cleanup();
227+
};
228+
229+
const cleanup = () => {
230+
for (const s of signals) s.removeEventListener("abort", onAbort);
231+
};
232+
233+
for (const s of signals) {
234+
if (s.aborted) {
235+
controller.abort(s.reason);
236+
return controller.signal;
237+
}
238+
s.addEventListener("abort", onAbort);
239+
}
240+
241+
return controller.signal;
242+
};
243+
}
244+
219245
/**
220246
* Combines user signal from context with an internal signal.
221247
*
@@ -304,6 +330,21 @@ export const toTask = <T, E>(
304330
]);
305331
}) as Task<T, E>;
306332

333+
// For React Native
334+
if (typeof AbortSignal.timeout !== "function") {
335+
AbortSignal.timeout = function (ms: number): AbortSignal {
336+
const controller = new AbortController();
337+
const id = setTimeout(() => {
338+
controller.abort();
339+
}, ms);
340+
// clear timeout if aborted early
341+
controller.signal.addEventListener("abort", () => {
342+
clearTimeout(id);
343+
});
344+
return controller.signal;
345+
};
346+
}
347+
307348
/**
308349
* Creates a {@link Task} that waits for the specified duration.
309350
*

0 commit comments

Comments
 (0)