{"version":3,"file":"useQueue.js","names":["useCallback","useRef","useQueue","queue","isProcessing","queueTask","fn","options","current","push","processQueue","beforeProcess","shouldContinue","length","latestTask","pop","err","console","error","afterProcess"],"sources":["../../src/hooks/useQueue.ts"],"sourcesContent":["import { useCallback, useRef } from 'react'\n\ntype QueuedFunction = () => Promise\n\ntype QueuedTaskOptions = {\n /**\n * A function that is called after the queue has processed a function\n * Used to perform side effects after processing the queue\n * @returns {void}\n */\n afterProcess?: () => void\n /**\n * A function that can be used to prevent the queue from processing under certain conditions\n * Can also be used to perform side effects before processing the queue\n * @returns {boolean} If `false`, the queue will not process\n */\n beforeProcess?: () => boolean | void\n}\n\ntype QueueTask = (fn: QueuedFunction, options?: QueuedTaskOptions) => void\n\n/**\n * A React hook that allows you to queue up functions to be executed in order.\n * This is useful when you need to ensure long running networks requests are processed sequentially.\n * Builds up a \"queue\" of functions to be executed in order, only ever processing the last function in the queue.\n * This ensures that a long queue of tasks doesn't cause a backlog of tasks to be processed.\n * E.g. if you queue a task and it begins running, then you queue 9 more tasks:\n * 1. The currently task will finish\n * 2. The next task in the queue will run\n * 3. All remaining tasks will be discarded\n * @returns {queueTask} A function used to queue a function.\n * @example\n * const { queueTask } = useQueue()\n * queueTask(async () => {\n * await fetch('https://api.example.com')\n * })\n */\nexport function useQueue(): {\n queueTask: QueueTask\n} {\n const queue = useRef([])\n\n const isProcessing = useRef(false)\n\n const queueTask = useCallback((fn, options) => {\n queue.current.push(fn)\n\n async function processQueue() {\n if (isProcessing.current) {\n return\n }\n\n // Allow the consumer to prevent the queue from processing under certain conditions\n if (typeof options?.beforeProcess === 'function') {\n const shouldContinue = options.beforeProcess()\n\n if (shouldContinue === false) {\n return\n }\n }\n\n while (queue.current.length > 0) {\n const latestTask = queue.current.pop() // Only process the last task in the queue\n queue.current = [] // Discard all other tasks\n\n isProcessing.current = true\n\n try {\n await latestTask()\n } catch (err) {\n console.error('Error in queued function:', err) // eslint-disable-line no-console\n } finally {\n isProcessing.current = false\n\n if (typeof options?.afterProcess === 'function') {\n options.afterProcess()\n }\n }\n }\n }\n\n void processQueue()\n }, [])\n\n return { queueTask }\n}\n"],"mappings":"AAAA,SAASA,WAAW,EAAEC,MAAM,QAAQ;AAqBpC;;;;;;;;;;;;;;;;AAgBA,OAAO,SAASC,SAAA;EAGd,MAAMC,KAAA,GAAQF,MAAA,CAAyB,EAAE;EAEzC,MAAMG,YAAA,GAAeH,MAAA,CAAO;EAE5B,MAAMI,SAAA,GAAYL,WAAA,CAAuB,CAACM,EAAA,EAAIC,OAAA;IAC5CJ,KAAA,CAAMK,OAAO,CAACC,IAAI,CAACH,EAAA;IAEnB,eAAeI,aAAA;MACb,IAAIN,YAAA,CAAaI,OAAO,EAAE;QACxB;MACF;MAEA;MACA,IAAI,OAAOD,OAAA,EAASI,aAAA,KAAkB,YAAY;QAChD,MAAMC,cAAA,GAAiBL,OAAA,CAAQI,aAAa;QAE5C,IAAIC,cAAA,KAAmB,OAAO;UAC5B;QACF;MACF;MAEA,OAAOT,KAAA,CAAMK,OAAO,CAACK,MAAM,GAAG,GAAG;QAC/B,MAAMC,UAAA,GAAaX,KAAA,CAAMK,OAAO,CAACO,GAAG,GAAG;AAAA;QACvCZ,KAAA,CAAMK,OAAO,GAAG,EAAE,EAAC;QAEnBJ,YAAA,CAAaI,OAAO,GAAG;QAEvB,IAAI;UACF,MAAMM,UAAA;QACR,EAAE,OAAOE,GAAA,EAAK;UACZC,OAAA,CAAQC,KAAK,CAAC,6BAA6BF,GAAA,GAAK;QAClD,UAAU;UACRZ,YAAA,CAAaI,OAAO,GAAG;UAEvB,IAAI,OAAOD,OAAA,EAASY,YAAA,KAAiB,YAAY;YAC/CZ,OAAA,CAAQY,YAAY;UACtB;QACF;MACF;IACF;IAEA,KAAKT,YAAA;EACP,GAAG,EAAE;EAEL,OAAO;IAAEL;EAAU;AACrB","ignoreList":[]}