import { Reaction } from "../classes"; import { MAX_REACTION_ITERATIONS } from "../constants"; import { runSubscribersCheck } from "./subscribersCheck"; let reactionQueue: Array = []; let isReactionRunScheduled = false; let reactionScheduler = (runner: () => void) => { Promise.resolve().then(runner).catch(reactionExceptionHandler); }; let reactionExceptionHandler = (exception: any) => { console.error("Reaction exception:", exception); }; export function setReactionScheduler(scheduler: typeof reactionScheduler) { reactionScheduler = scheduler; } export function setReactionExceptionHandler(handler: typeof reactionExceptionHandler) { reactionExceptionHandler = handler; } export function scheduleReaction(reaction: Reaction) { reactionQueue.push(reaction); } function runReactions(): void { try { let i = MAX_REACTION_ITERATIONS; while ((reactionQueue.length) && --i) { const reactions = reactionQueue; reactionQueue = []; reactions.forEach((reaction) => { try { reaction.runManager(); } catch (exception: any) { reactionExceptionHandler(exception); } }); } if (!i) { throw new Error("Infinite reactions loop"); } } finally { isReactionRunScheduled = false; reactionQueue = []; runSubscribersCheck(); } } export function scheduleReactionRunner(): void { const shouldRunReactions = reactionQueue.length; if (!isReactionRunScheduled && shouldRunReactions) { isReactionRunScheduled = true; reactionScheduler(runReactions); } }