PriorityQueue.js 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. class PriorityQueue {
  2. constructor( maxJobs = 6 ) {
  3. // options
  4. this.maxJobs = maxJobs;
  5. this.items = [];
  6. this.currJobs = 0;
  7. this.scheduled = false;
  8. }
  9. add( item, priority, callback ) {
  10. return new Promise( ( resolve, reject ) => {
  11. const prCallback = ( ...args ) => callback( ...args ).then( resolve ).catch( reject );
  12. const items = this.items;
  13. for ( let i = 0, l = items.length; i < l; i ++ ) {
  14. const thisItem = items[ i ];
  15. if ( thisItem.priority > priority ) {
  16. items.splice( i, 0, { priority, item, callback: prCallback } );
  17. this.scheduleJobRun();
  18. return;
  19. }
  20. }
  21. items.push( { priority, item, callback: prCallback } );
  22. this.scheduleJobRun();
  23. } );
  24. }
  25. remove( item ) {
  26. const items = this.items;
  27. for ( let i = 0, l = items.length; i < l; i ++ ) {
  28. const thisItem = items[ i ];
  29. if ( thisItem.item === item ) {
  30. items.splice( i, 1 );
  31. break;
  32. }
  33. }
  34. }
  35. tryRunJobs() {
  36. const items = this.items;
  37. const maxJobs = this.maxJobs;
  38. while ( maxJobs > this.currJobs && items.length > 0 ) {
  39. this.currJobs ++;
  40. const { item, priority, callback } = items.pop();
  41. callback( item, priority )
  42. .then( () => {
  43. this.currJobs --;
  44. this.scheduleJobRun();
  45. } )
  46. .catch( () => {
  47. this.currJobs --;
  48. this.scheduleJobRun();
  49. } );
  50. }
  51. }
  52. scheduleJobRun() {
  53. if ( ! this.scheduled ) {
  54. Promise.resolve().then( () => {
  55. this.tryRunJobs();
  56. this.scheduled = false;
  57. } );
  58. this.scheduled = true;
  59. }
  60. }
  61. }
  62. export { PriorityQueue };