UNPKG

evnty

Version:

Async-first, reactive event handling library for complex event flows in browser and Node.js

115 lines (113 loc) 3.43 kB
import { isThenable, noop } from "./utils.js"; const ERR_BRAND = Symbol.for('evnty.ResultError'); function ResultError(error) { this.error = error; } ResultError.prototype[ERR_BRAND] = true; export function err(error) { return new ResultError(error); } export function isErr(result) { return typeof result === 'object' && result !== null && result[ERR_BRAND] === true; } export function isOk(result) { return typeof result !== 'object' || result === null || !result[ERR_BRAND]; } export function unwrap(results) { const len = results.length; const unwrapped = new Array(len); for(let i = 0; i < len; i++){ const r = results[i]; unwrapped[i] = isErr(r) ? Promise.reject(r.error) : r; } return unwrapped; } async function resolveMaybePromises(items, asyncIndices) { const pending = new Array(asyncIndices.length); for(let j = 0; j < asyncIndices.length; j++){ pending[j] = items[asyncIndices[j]]; } const resolved = await Promise.all(pending); for(let j = 0; j < asyncIndices.length; j++){ items[asyncIndices[j]] = resolved[j]; } return items; } function resolveAll(results) { const len = results.length; if (len === 0) return results; let firstError; let hasError = false; let asyncIndices = null; for(let i = 0; i < len; i++){ const r = results[i]; if (isErr(r)) { if (!hasError) { hasError = true; firstError = r.error; } } else if (isThenable(r)) { (asyncIndices ??= []).push(i); } } if (hasError) { if (asyncIndices !== null) { for(let j = 0; j < asyncIndices.length; j++){ results[asyncIndices[j]].then(noop, noop); } } return Promise.reject(firstError); } if (asyncIndices === null) return results; return resolveMaybePromises(results, asyncIndices); } function settleAll(results) { const len = results.length; if (len === 0) return []; let asyncIndices = null; const settled = new Array(len); for(let i = 0; i < len; i++){ const r = results[i]; if (isErr(r)) { settled[i] = { status: 'rejected', reason: r.error }; } else if (isThenable(r)) { (asyncIndices ??= []).push(i); settled[i] = r.then((value)=>({ status: 'fulfilled', value }), (reason)=>({ status: 'rejected', reason })); } else { settled[i] = { status: 'fulfilled', value: r }; } } if (asyncIndices === null) return settled; return resolveMaybePromises(settled, asyncIndices); } export class DispatchResult { #results; [Symbol.toStringTag] = 'DispatchResult'; constructor(results){ this.#results = results; } then(onfulfilled, onrejected) { const resolved = this.all(); if (resolved instanceof Promise) return resolved.then(onfulfilled, onrejected); return Promise.resolve(resolved).then(onfulfilled, onrejected); } all() { return resolveAll(this.#results); } settled() { return settleAll(this.#results); } } //# sourceMappingURL=dispatch-result.js.map