UNPKG

@exabytellc/utils

Version:

EB react utils to make everything a little easier!

222 lines (202 loc) 5.88 kB
import { round } from "../math"; export default class HttpRequest { // const #states = { 0: "unsent", 1: "opened", 2: "uploading", 3: "processing", 4: "downloading", 5: "completed", }; get requestStates() { return this.#states; } // params #request = new XMLHttpRequest(); #method = null; #address = null; #headers = null; #urlData = null; #bodyData = null; #responseType = null; #onStateChange = null; // output #httpCode = null; #state = null; #stateText = null; #error = null; #response = null; #currentStats = { 0: null, 1: null, 2: null, 3: null, 4: null, 5: null, }; #uploadCalc = { start: null, total: 0, loaded: 0, }; #upload = { duration: 0, progress: 0, speed: 0, eta: 0, } #downloadCalc = { start: null, total: 0, loaded: 0, }; #download = { duration: 0, // milliseconds. progress: 0, // % speed: 0, // bytes per millisecond eta: 0, // milliseconds. } // getters get request() { return this.#request; } get httpCode() { return this.#httpCode; } get currentState() { return this.#state; } get currentStateText() { return this.#stateText; } get error() { return this.#error; } get response() { return this.#response; } get currentStats() { return this.#currentStats; } get currentUpload() { return this.#upload; } get currentDownload() { return this.#download; } // constructor constructor({ method = "GET", address = null, headers = null, urlData = null, bodyData = null, responseType = "json", onStateChange = null, } = {}) { this.#method = method; this.#address = address; this.#headers = headers; this.#urlData = urlData; this.#bodyData = bodyData; this.#responseType = responseType; this.#onStateChange = onStateChange; this.#buildUrlWithQueryParams(); this.#setState(0, null); } async send() { this.#configureRequest(); this.#registerEventListeners(); await this.#handleResponse(); } #buildUrlWithQueryParams() { if (this.#urlData) { const queryParams = new URLSearchParams(this.#urlData).toString(); this.#address += `?${queryParams}`; } } #configureRequest() { if (this.#responseType) { this.#request.responseType = this.#responseType; } this.#request.open(this.#method, this.#address, true); if (this.#headers) { for (const [key, value] of Object.entries(this.#headers)) { this.#request.setRequestHeader(key, value); } } } #registerEventListeners() { this.#request.onloadstart = () => this.#setState(1, null); this.#request.upload.onloadstart = (event) => { if (this.#onStateChange) this.#calcTransferRate(this.#uploadCalc, this.#upload, event.total, event.loaded); this.#setState(2, null); }; this.#request.upload.onprogress = (event) => { if (this.#onStateChange) this.#calcTransferRate(this.#uploadCalc, this.#upload, event.total, event.loaded); this.#setState(2, null); }; this.#request.upload.onloadend = (event) => { if (this.#onStateChange) this.#calcTransferRate(this.#uploadCalc, this.#upload, event.total, event.loaded); this.#setState(3, null); }; this.#request.onprogress = (event) => { if (this.#onStateChange) this.#calcTransferRate(this.#downloadCalc, this.#download, event.total, event.loaded); this.#setState(4, null); }; this.#request.ontimeout = () => { this.#setState(5, "timeout"); }; this.#request.onabort = () => { this.#setState(5, "aborted"); }; this.#request.onerror = () => { this.#setState(5, "failed"); }; } async #handleResponse() { return new Promise((resolve) => { this.#request.onloadend = (event) => { if (this.#onStateChange) this.#calcTransferRate(this.#downloadCalc, this.#download, event.total, event.loaded); this.#response = this.#request.response; this.#setState(5, null); resolve(); }; this.#request.send(this.#bodyData); }); } #calcTransferRate(calcObj, outObj, total, loaded) { calcObj.total = total; calcObj.loaded = loaded; outObj.progress = round(((calcObj.loaded / calcObj.total) * 100), 2); if (!calcObj.start) { calcObj.start = new Date().getTime(); } else { outObj.duration = new Date().getTime() - calcObj.start; if (outObj.progress == 100) { outObj.speed = 0; outObj.eta = 0; } else { outObj.speed = round((calcObj.loaded / outObj.duration) || 0, 2); outObj.eta = round(((calcObj.total - calcObj.loaded) / outObj.speed) || 0, 2); } } } #setState(state, error = null) { this.#httpCode = this.#request.status; this.#state = state; this.#stateText = this.#states[state]; this.#error = error; if (!this.#currentStats[state]) { this.#currentStats[state] = new Date().getTime(); if (state > 0) { this.#currentStats[state - 1] = this.#currentStats[state] - (this.#currentStats[state - 1] ?? 0); } } if (this.#onStateChange) this.#onStateChange(this); } static async quickCall({ method = null, address = null, headers = null, urlData = null, bodyData = null, responseType = null, onStateChange = null }) { const request = new HttpRequest({ method, address, headers, urlData, bodyData, responseType, onStateChange }); await request.send(); const res = request?.response; return res; } }