UNPKG

suspenders-js

Version:

Asynchronous programming library utilizing coroutines, functional reactive programming and structured concurrency.

122 lines 3.67 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.httpGet = exports.promiseSuspender = exports.awaitCancelation = exports.wait = exports.race = exports.async = void 0; /** * Starts the suspender but doesn't wait for it's result. Returns a new suspender that returns the * result. * @param {Suspender<T>} suspender * @return {Suspender<T>} */ const async = (suspender) => { let result; let resultCallback; return (resCallback) => { if (result !== undefined) { resCallback(result); } else { resultCallback = resCallback; } return suspender((res) => { if (resultCallback !== undefined) { resultCallback(res); } else { result = res; } }); }; }; exports.async = async; /** * Returns the first suspender to resolve successfully. All other pending suspenders are canceled. * If all suspenders error, throws the last error. * @params {Array<Suspender<T>>} suspenders * @return {Suspender<T>} */ const race = (...suspenders) => { return (resultCallback) => { const cancelCallbacks = []; for (let [index, suspender] of suspenders.entries()) { cancelCallbacks.push(suspender((value) => { cancelCallbacks[index] = null; // cancel all other suspenders for (let m = 0; m < suspenders.length; m++) { const cancel = cancelCallbacks[m]; if (cancel) { cancel(); } else { cancelCallbacks[m] = null; } } resultCallback(value); })); } return () => { for (const cancelCallback of cancelCallbacks) { if (cancelCallback) { cancelCallback(); } } }; }; }; exports.race = race; /** * Returns a suspender that resolves with given timout. * @param {number} millis * @return {Suspender<void>} */ const wait = (millis) => { return (resultCallback) => { const timeout = setTimeout(() => { resultCallback({ value: undefined }); }, millis); return () => { clearTimeout(timeout); }; }; }; exports.wait = wait; const awaitCancelation = () => { return () => { }; }; exports.awaitCancelation = awaitCancelation; /** * Converts a Promise<T> to a Suspender<T>. * @param {Promise<T>} promise * @return {Suspender<T>} */ const promiseSuspender = (promise) => { return (resultCallback) => { promise.then((value) => { resultCallback({ value }); }, (error) => { resultCallback({ tag: `error`, error }); }); }; }; exports.promiseSuspender = promiseSuspender; /** * Performs an http get on url. Returns body on 200 or throws error. * @param {string} url * @return {Suspender<T>} */ const httpGet = (url) => { return (resultCallback) => { const xhttp = new XMLHttpRequest(); xhttp.onloadend = function () { if (this.status === 200) { resultCallback({ value: this.responseText }); } else { resultCallback({ tag: `error`, error: new Error(`code: ${this.status} text: ${this.statusText}`) }); } }; xhttp.open(`GET`, url, true); xhttp.send(); return () => { xhttp.abort(); }; }; }; exports.httpGet = httpGet; //# sourceMappingURL=Util.js.map