123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- // Fires at the end of the frame and before the next one
- function enqueueMicrotask( callback ) {
- Promise.resolve().then( callback );
- }
- class PriorityQueue {
- constructor() {
- // options
- this.maxJobs = 6;
- this.items = [];
- this.callbacks = new Map();
- this.currJobs = 0;
- this.scheduled = false;
- this.autoUpdate = true;
- this.priorityCallback = () => {
- throw new Error( 'PriorityQueue: PriorityCallback function not defined.' );
- };
- }
- sort() {
- const priorityCallback = this.priorityCallback;
- const items = this.items;
- items.sort( ( a, b ) => {
- return priorityCallback( a ) - priorityCallback( b );
- } );
- }
- add( item, callback ) {
- return new Promise( ( resolve, reject ) => {
- const prCallback = ( ...args ) => callback( ...args ).then( resolve ).catch( reject );
- const items = this.items;
- const callbacks = this.callbacks;
- items.push( item );
- callbacks.set( item, prCallback );
- if ( this.autoUpdate ) {
- this.scheduleJobRun();
- }
- } );
- }
- remove( item ) {
- const items = this.items;
- const callbacks = this.callbacks;
- const index = items.indexOf( item );
- if ( index !== - 1 ) {
- items.splice( index, 1 );
- callbacks.delete( item );
- }
- }
- tryRunJobs() {
- this.sort();
- const items = this.items;
- const callbacks = this.callbacks;
- const maxJobs = this.maxJobs;
- let currJobs = this.currJobs;
- while ( maxJobs > currJobs && items.length > 0 ) {
- currJobs ++;
- const item = items.pop();
- const callback = callbacks.get( item );
- callbacks.delete( item );
- callback( item )
- .then( () => {
- this.currJobs --;
- if ( this.autoUpdate ) {
- this.scheduleJobRun();
- }
- } )
- .catch( () => {
- this.currJobs --;
- if ( this.autoUpdate ) {
- this.scheduleJobRun();
- }
- } );
- }
- this.currJobs = currJobs;
- }
- scheduleJobRun() {
- if ( ! this.scheduled ) {
- enqueueMicrotask( () => {
- this.tryRunJobs();
- this.scheduled = false;
- } );
- this.scheduled = true;
- }
- }
- }
- export { PriorityQueue };
|