UNPKG

@wordpress/priority-queue

Version:
8 lines (7 loc) 6.34 kB
{ "version": 3, "sources": ["../src/index.ts"], "sourcesContent": ["/**\n * Internal dependencies\n */\nimport requestIdleCallback from './request-idle-callback';\n\n/**\n * Enqueued callback to invoke once idle time permits.\n */\nexport type WPPriorityQueueCallback = VoidFunction;\n\n/**\n * An object used to associate callbacks in a particular context grouping.\n */\nexport type WPPriorityQueueContext = object;\n\n/**\n * Interface for the priority queue instance.\n */\nexport interface WPPriorityQueue {\n\t/**\n\t * Add a callback to the queue for a given context.\n\t */\n\tadd: (\n\t\telement: WPPriorityQueueContext,\n\t\titem: WPPriorityQueueCallback\n\t) => void;\n\n\t/**\n\t * Flush and run the callback for a given context immediately.\n\t * @return true if a callback was run, false otherwise.\n\t */\n\tflush: ( element: WPPriorityQueueContext ) => boolean;\n\n\t/**\n\t * Cancel (remove) the callback for a given context without running it.\n\t * @return true if a callback was cancelled, false otherwise.\n\t */\n\tcancel: ( element: WPPriorityQueueContext ) => boolean;\n\n\t/**\n\t * Reset the entire queue, clearing pending callbacks.\n\t */\n\treset: VoidFunction;\n}\n\n/**\n * Creates a context-aware queue that only executes\n * the last task of a given context.\n *\n * @example\n *```js\n * import { createQueue } from '@wordpress/priority-queue';\n *\n * const queue = createQueue();\n *\n * // Context objects.\n * const ctx1 = {};\n * const ctx2 = {};\n *\n * // For a given context in the queue, only the last callback is executed.\n * queue.add( ctx1, () => console.log( 'This will be printed first' ) );\n * queue.add( ctx2, () => console.log( 'This won\\'t be printed' ) );\n * queue.add( ctx2, () => console.log( 'This will be printed second' ) );\n *```\n *\n * @return {WPPriorityQueue} Queue object with `add`, `flush` and `reset` methods.\n */\nexport const createQueue = (): WPPriorityQueue => {\n\tconst waitingList = new Map<\n\t\tWPPriorityQueueContext,\n\t\tWPPriorityQueueCallback\n\t>();\n\tlet isRunning = false;\n\n\t/**\n\t * Callback to process as much queue as time permits.\n\t *\n\t * Map Iteration follows the original insertion order. This means that here\n\t * we can iterate the queue and know that the first contexts which were\n\t * added will be run first. On the other hand, if anyone adds a new callback\n\t * for an existing context it will supplant the previously-set callback for\n\t * that context because we reassigned that map key's value.\n\t *\n\t * In the case that a callback adds a new callback to its own context then\n\t * the callback it adds will appear at the end of the iteration and will be\n\t * run only after all other existing contexts have finished executing.\n\t *\n\t * @param {IdleDeadline|number} deadline Idle callback deadline object, or\n\t * animation frame timestamp.\n\t */\n\tconst runWaitingList = ( deadline: IdleDeadline | number ): void => {\n\t\tfor ( const [ nextElement, callback ] of waitingList ) {\n\t\t\twaitingList.delete( nextElement );\n\t\t\tcallback();\n\n\t\t\tif (\n\t\t\t\t'number' === typeof deadline ||\n\t\t\t\tdeadline.timeRemaining() <= 0\n\t\t\t) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif ( waitingList.size === 0 ) {\n\t\t\tisRunning = false;\n\t\t\treturn;\n\t\t}\n\n\t\trequestIdleCallback( runWaitingList );\n\t};\n\n\t/**\n\t * Add a callback to the queue for a given context.\n\t *\n\t * If errors with undefined callbacks are encountered double check that\n\t * all of your useSelect calls have the right dependencies set correctly\n\t * in their second parameter. Missing dependencies can cause unexpected\n\t * loops and race conditions in the queue.\n\t *\n\t * @param {WPPriorityQueueContext} element Context object.\n\t * @param {WPPriorityQueueCallback} item Callback function.\n\t */\n\tconst add: WPPriorityQueue[ 'add' ] = (\n\t\telement: WPPriorityQueueContext,\n\t\titem: WPPriorityQueueCallback\n\t) => {\n\t\twaitingList.set( element, item );\n\t\tif ( ! isRunning ) {\n\t\t\tisRunning = true;\n\t\t\trequestIdleCallback( runWaitingList );\n\t\t}\n\t};\n\n\t/**\n\t * Flushes queue for a given context, returning true if the flush was\n\t * performed, or false if there is no queue for the given context.\n\t *\n\t * @param {WPPriorityQueueContext} element Context object.\n\t *\n\t * @return {boolean} Whether flush was performed.\n\t */\n\tconst flush: WPPriorityQueue[ 'flush' ] = (\n\t\telement: WPPriorityQueueContext\n\t) => {\n\t\tconst callback = waitingList.get( element );\n\t\tif ( undefined === callback ) {\n\t\t\treturn false;\n\t\t}\n\n\t\twaitingList.delete( element );\n\t\tcallback();\n\n\t\treturn true;\n\t};\n\n\t/**\n\t * Clears the queue for a given context, cancelling the callbacks without\n\t * executing them. Returns `true` if there were scheduled callbacks to cancel,\n\t * or `false` if there was is no queue for the given context.\n\t *\n\t * @param {WPPriorityQueueContext} element Context object.\n\t *\n\t * @return {boolean} Whether any callbacks got cancelled.\n\t */\n\tconst cancel: WPPriorityQueue[ 'cancel' ] = (\n\t\telement: WPPriorityQueueContext\n\t) => {\n\t\treturn waitingList.delete( element );\n\t};\n\n\t/**\n\t * Reset the queue without running the pending callbacks.\n\t */\n\tconst reset: WPPriorityQueue[ 'reset' ] = () => {\n\t\twaitingList.clear();\n\t\tisRunning = false;\n\t};\n\n\treturn {\n\t\tadd,\n\t\tflush,\n\t\tcancel,\n\t\treset,\n\t};\n};\n"], "mappings": ";AAGA,OAAO,yBAAyB;AAgEzB,IAAM,cAAc,MAAuB;AACjD,QAAM,cAAc,oBAAI,IAGtB;AACF,MAAI,YAAY;AAkBhB,QAAM,iBAAiB,CAAE,aAA2C;AACnE,eAAY,CAAE,aAAa,QAAS,KAAK,aAAc;AACtD,kBAAY,OAAQ,WAAY;AAChC,eAAS;AAET,UACC,aAAa,OAAO,YACpB,SAAS,cAAc,KAAK,GAC3B;AACD;AAAA,MACD;AAAA,IACD;AAEA,QAAK,YAAY,SAAS,GAAI;AAC7B,kBAAY;AACZ;AAAA,IACD;AAEA,wBAAqB,cAAe;AAAA,EACrC;AAaA,QAAM,MAAgC,CACrC,SACA,SACI;AACJ,gBAAY,IAAK,SAAS,IAAK;AAC/B,QAAK,CAAE,WAAY;AAClB,kBAAY;AACZ,0BAAqB,cAAe;AAAA,IACrC;AAAA,EACD;AAUA,QAAM,QAAoC,CACzC,YACI;AACJ,UAAM,WAAW,YAAY,IAAK,OAAQ;AAC1C,QAAK,WAAc,UAAW;AAC7B,aAAO;AAAA,IACR;AAEA,gBAAY,OAAQ,OAAQ;AAC5B,aAAS;AAET,WAAO;AAAA,EACR;AAWA,QAAM,SAAsC,CAC3C,YACI;AACJ,WAAO,YAAY,OAAQ,OAAQ;AAAA,EACpC;AAKA,QAAM,QAAoC,MAAM;AAC/C,gBAAY,MAAM;AAClB,gBAAY;AAAA,EACb;AAEA,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;", "names": [] }