PriorityQueue.js 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. class PriorityQueue {
  2. constructor() {
  3. // options
  4. this.maxJobs = 6;
  5. this.items = [];
  6. this.callbacks = new Map();
  7. this.currJobs = 0;
  8. this.scheduled = false;
  9. this.autoUpdate = true;
  10. this.priorityCallback = () => {
  11. throw new Error( 'PriorityQueue: PriorityCallback function not defined.' );
  12. };
  13. }
  14. sort() {
  15. const priorityCallback = this.priorityCallback;
  16. const items = this.items;
  17. items.sort( ( a, b ) => {
  18. return priorityCallback( a ) - priorityCallback( b );
  19. } );
  20. }
  21. add( item, callback ) {
  22. return new Promise( ( resolve, reject ) => {
  23. const prCallback = ( ...args ) => callback( ...args ).then( resolve ).catch( reject );
  24. const items = this.items;
  25. const callbacks = this.callbacks;
  26. items.push( item );
  27. callbacks.set( item, prCallback );
  28. if ( this.autoUpdate ) {
  29. this.scheduleJobRun();
  30. }
  31. } );
  32. }
  33. remove( item ) {
  34. const items = this.items;
  35. const callbacks = this.callbacks;
  36. const index = items.indexOf( item );
  37. if ( index !== - 1 ) {
  38. items.splice( index, 1 );
  39. callbacks.delete( item );
  40. }
  41. }
  42. tryRunJobs() {
  43. this.sort();
  44. const items = this.items;
  45. const callbacks = this.callbacks;
  46. const maxJobs = this.maxJobs;
  47. let currJobs = this.currJobs;
  48. while ( maxJobs > currJobs && items.length > 0 ) {
  49. currJobs ++;
  50. const item = items.pop();
  51. const callback = callbacks.get( item );
  52. callbacks.delete( item );
  53. callback( item )
  54. .then( () => {
  55. this.currJobs --;
  56. if ( this.autoUpdate ) {
  57. this.scheduleJobRun();
  58. }
  59. } )
  60. .catch( () => {
  61. this.currJobs --;
  62. if ( this.autoUpdate ) {
  63. this.scheduleJobRun();
  64. }
  65. } );
  66. }
  67. this.currJobs = currJobs;
  68. }
  69. scheduleJobRun() {
  70. if ( ! this.scheduled ) {
  71. requestAnimationFrame( () => {
  72. this.tryRunJobs();
  73. this.scheduled = false;
  74. } );
  75. this.scheduled = true;
  76. }
  77. }
  78. }
  79. export { PriorityQueue };