UNPKG

@lifaon/rx-js-light

Version:

Blazing fast Observables

122 lines (121 loc) 5.55 kB
import {isAbortError} from "../../../../../../../misc/errors/abort-error/is-abort-error.mjs"; import {createNetworkErrorFromRequest} from "../../../../../../../misc/errors/network-error/create-network-error.mjs"; import {createEventListener} from "../../../../../../../misc/event-listener/functions/create-event-listener.mjs"; import {toTypedEventTarget} from "../../../../../../../misc/event-listener/functions/to-typed-event-target.mjs"; import {noop} from "../../../../../../../misc/helpers/noop.mjs"; import {STATIC_COMPLETE_NOTIFICATION} from "../../../../../../../misc/notifications/built-in/complete/complete-notification.constant.mjs"; import {createDownloadProgressNotification} from "../../../../../../../misc/notifications/built-in/download-progress/create-download-progress-notification.mjs"; import {createErrorNotification} from "../../../../../../../misc/notifications/built-in/error/create-error-notification.mjs"; import {createAbortErrorNotification} from "../../../../../../../misc/notifications/built-in/error/derived/create-abort-error-notification.mjs"; import {createNextNotification} from "../../../../../../../misc/notifications/built-in/next/create-next-notification.mjs"; import {STATIC_UPLOAD_COMPLETE_NOTIFICATION} from "../../../../../../../misc/notifications/built-in/upload-complete/upload-complete-notification.constant.mjs"; import {createUploadProgressNotification} from "../../../../../../../misc/notifications/built-in/upload-progress/create-upload-progress-notification.mjs"; import {createProgressFromProgressEvent} from "../../../../../../../misc/progress/create-progress-from-progress-event.mjs"; import {areReadableStreamSupported, initAndSendXHRFromRequest, XHRResponse, XHRResponseToReadableStream, XHRResponseToResponse, XHRResponseToResponseInit} from "../xhr-helpers.mjs"; export function fromXHR(requestInfo, requestInit, options) { const request = new Request(requestInfo, requestInit); const useReadableStream = areReadableStreamSupported() && (options === void 0 || options.useReadableStream === void 0 ? true : options.useReadableStream); return emit => { if (request.signal.aborted) { emit(createAbortErrorNotification({ signal: request.signal })); return noop; } else { let running = true; const xhr = new XMLHttpRequest(); let stream; let responseType; if (useReadableStream) { responseType = 'binary-string'; stream = XHRResponseToReadableStream(xhr, responseType); } else { responseType = 'blob'; } const end = () => { running = false; removeReadyStateChangeEventListener(); removeLoadEventListener(); removeErrorEventListener(); removeAbortEventListener(); removeDownloadProgressEventListener(); removeUploadProgressEventListener(); removeUploadCompleteEventListener(); }; const next = response => { emit(createNextNotification(response)); }; const complete = () => { if (running) { end(); emit(STATIC_COMPLETE_NOTIFICATION); } }; const error = error => { if (running) { end(); emit(createErrorNotification(error)); } }; const abort = () => { if (running) { end(); emit(createAbortErrorNotification({ signal: request.signal })); } }; const downloadProgress = progress => { if (running) { emit(createDownloadProgressNotification(progress)); } }; const uploadProgress = progress => { if (running) { emit(createUploadProgressNotification(progress)); } }; const uploadComplete = () => { if (running) { emit(STATIC_UPLOAD_COMPLETE_NOTIFICATION); } }; const removeReadyStateChangeEventListener = createEventListener(toTypedEventTarget(xhr), 'readystatechange', () => { if (running) { if (stream === void 0) { if (xhr.readyState === xhr.DONE) { next(XHRResponseToResponse(xhr, responseType)); } } else { if (xhr.readyState === xhr.HEADERS_RECEIVED) { next(new XHRResponse(stream, XHRResponseToResponseInit(xhr))); } } } }); const removeLoadEventListener = createEventListener(toTypedEventTarget(xhr), 'load', complete); const removeErrorEventListener = createEventListener(toTypedEventTarget(xhr), 'error', () => { error(createNetworkErrorFromRequest(request)); }); const removeAbortEventListener = createEventListener(toTypedEventTarget(xhr), 'abort', abort); const removeDownloadProgressEventListener = createEventListener(toTypedEventTarget(xhr), 'progress', event => { downloadProgress(createProgressFromProgressEvent(event)); }); const removeUploadProgressEventListener = createEventListener(toTypedEventTarget(xhr.upload), 'progress', event => { uploadProgress(createProgressFromProgressEvent(event)); }); const removeUploadCompleteEventListener = createEventListener(toTypedEventTarget(xhr.upload), 'load', uploadComplete); initAndSendXHRFromRequest(xhr, responseType, request).catch(error => { if (!isAbortError(error)) { throw error; } }); return () => { if (running) { end(); xhr.abort(); } }; } }; }