batcher.js 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. var _ = require('./util')
  2. /**
  3. * The Batcher maintains a job queue to be run
  4. * async on the next event loop.
  5. */
  6. function Batcher () {
  7. this._preFlush = null
  8. this.reset()
  9. }
  10. var p = Batcher.prototype
  11. /**
  12. * Push a job into the job queue.
  13. * Jobs with duplicate IDs will be skipped, however we can
  14. * use the `override` option to override existing jobs.
  15. *
  16. * @param {Object} job
  17. * properties:
  18. * - {String|Number} id
  19. * - {Boolean} override
  20. * - {Function} run
  21. */
  22. p.push = function (job) {
  23. if (!job.id || !this.has[job.id]) {
  24. this.queue.push(job)
  25. this.has[job.id] = job
  26. if (!this.waiting) {
  27. this.waiting = true
  28. _.nextTick(this.flush, this)
  29. }
  30. } else if (job.override) {
  31. var oldJob = this.has[job.id]
  32. oldJob.cancelled = true
  33. this.queue.push(job)
  34. this.has[job.id] = job
  35. }
  36. }
  37. /**
  38. * Flush the queue and run the jobs.
  39. * Will call a preFlush hook if has one.
  40. */
  41. p.flush = function () {
  42. // before flush hook
  43. if (this._preFlush) {
  44. this._preFlush()
  45. }
  46. // do not cache length because more jobs might be pushed
  47. // as we run existing jobs
  48. for (var i = 0; i < this.queue.length; i++) {
  49. var job = this.queue[i]
  50. if (!job.cancelled) {
  51. job.run()
  52. }
  53. }
  54. this.reset()
  55. }
  56. /**
  57. * Reset the batcher's state.
  58. */
  59. p.reset = function () {
  60. this.has = {}
  61. this.queue = []
  62. this.waiting = false
  63. }
  64. module.exports = Batcher