import { Actual } from "base/Actual"; import { Message } from "base/Message"; import { MaybeMessage } from "types/MessageType"; type ExtractTypeS = T extends MaybeMessage ? U : never; type ExtractTypesFromArrayS[]> = { [K in keyof T]: ExtractTypeS; }; const isAllFilled = (keysFilled: Set, keysKnown: Set) => { return keysFilled.size > 0 && keysFilled.size === keysKnown.size; }; /** * A message that represents values from * all provided messages as an array. * When all messages emit their values, * the combined value will be returned. * If at least one message later emits a new * value, the updated array with the new value * will be emitted by All. * * @url https://silentium.pw/article/all-component/view */ export function All(...messages: T) { const $messages = messages.map(Actual); return Message>(function AllImpl(resolve, reject) { const known = new Set(Object.keys(messages)); const filled = new Set(); const result: unknown[] = []; if (known.size === 0) { resolve([] as ExtractTypesFromArrayS); return; } $messages.map(function allMessagesMap(m, key) { m.catch(reject); m.then(function allMessageSub(v) { filled.add(key.toString()); result[key] = v; if (isAllFilled(filled, known)) { resolve(result.slice() as ExtractTypesFromArrayS); } }); }); }); }