UNPKG

expo

Version:
61 lines (53 loc) 2.07 kB
import { ExpoFetchModule } from './ExpoFetchModule'; import { FetchError } from './FetchErrors'; import { FetchResponse, type AbortSubscriptionCleanupFunction } from './FetchResponse'; import { NativeRequest, NativeRequestInit } from './NativeRequest'; import { normalizeBodyInitAsync, normalizeHeadersInit, overrideHeaders } from './RequestUtils'; import type { FetchRequestInit } from './fetch.types'; // TODO(@kitten): Do we really want to use our own types for web standards? export async function fetch(url: string, init?: FetchRequestInit): Promise<FetchResponse> { let abortSubscription: AbortSubscriptionCleanupFunction | null = null; const response = new FetchResponse(() => { abortSubscription?.(); }); const request = new ExpoFetchModule.NativeRequest(response) as NativeRequest; let headers = normalizeHeadersInit(init?.headers); const { body: requestBody, overriddenHeaders } = await normalizeBodyInitAsync(init?.body); if (overriddenHeaders) { headers = overrideHeaders(headers, overriddenHeaders); } const nativeRequestInit: NativeRequestInit = { credentials: init?.credentials ?? 'include', headers, method: init?.method ?? 'GET', redirect: init?.redirect ?? 'follow', }; if (init?.signal && init.signal.aborted) { throw new FetchError('The operation was aborted.'); } abortSubscription = addAbortSignalListener(init?.signal, () => { request.cancel(); }); try { await request.start(url, nativeRequestInit, requestBody); } catch (e: unknown) { if (e instanceof Error) { throw FetchError.createFromError(e); } else { throw new FetchError(String(e)); } } return response; } /** * A wrapper of `AbortSignal.addEventListener` that returns a cleanup function. */ function addAbortSignalListener( signal: AbortSignal | undefined, listener: Parameters<AbortSignal['addEventListener']>[1] ): AbortSubscriptionCleanupFunction { signal?.addEventListener('abort', listener); return () => { signal?.removeEventListener('abort', listener); }; }