@lifaon/rx-js-light
Version:
Blazing fast Observables
122 lines (121 loc) • 5.55 kB
JavaScript
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();
}
};
}
};
}