index.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /*@flow*/
  2. /*
  3. * Caleb James DeLisle
  4. * Sat Mar 23 01:42:29 EDT 2013
  5. * Public Domain or MIT License
  6. */
  7. /*::
  8. export type Nthen_WaitFor_t = {
  9. (?(...any)=>any): (...any)=>any,
  10. abort: ()=>void
  11. };
  12. export type Nthen_Ret_t = {
  13. nThen: Nthen_t,
  14. orTimeout:((Nthen_WaitFor_t)=>void, number)=>Nthen_Ret_t
  15. };
  16. export type Nthen_t = ((Nthen_WaitFor_t)=>void)=>Nthen_Ret_t;
  17. module.exports = */ (function() {
  18. var nThen /*:Nthen_t*/ = function(next) {
  19. var funcs /*:Array<(Nthen_WaitFor_t)=>void>*/ = [];
  20. var timeouts = [];
  21. var calls = 0;
  22. var abort;
  23. var inNthen = 0;
  24. var callNext = function (arg) {
  25. inNthen++;
  26. funcs.shift()(arg);
  27. inNthen--;
  28. };
  29. var waitFor /*:Nthen_WaitFor_t*/ = function(func) {
  30. calls++;
  31. return function() {
  32. var args = Array.prototype.slice.call(arguments);
  33. var f = function () {
  34. var ret;
  35. if (func) {
  36. ret = func.apply(null, args);
  37. }
  38. calls = (calls || 1) - 1;
  39. while (!calls && funcs.length && !abort) {
  40. callNext(waitFor);
  41. }
  42. return ret;
  43. };
  44. if (inNthen) {
  45. setTimeout(f);
  46. } else {
  47. f();
  48. }
  49. };
  50. };
  51. waitFor.abort = function () {
  52. timeouts.forEach(clearTimeout);
  53. abort = 1;
  54. };
  55. var ret = {
  56. nThen: function(next) {
  57. if (!abort) {
  58. if (!calls) {
  59. inNthen++;
  60. next(waitFor);
  61. inNthen--;
  62. } else {
  63. funcs.push(next);
  64. }
  65. }
  66. return ret;
  67. },
  68. orTimeout: function(func, milliseconds) {
  69. if (abort) { return ret; }
  70. if (!milliseconds) { throw Error("Must specify milliseconds to orTimeout()"); }
  71. var cto;
  72. var timeout = setTimeout(function() {
  73. while (funcs.shift() !== cto) { }
  74. inNthen++;
  75. func(waitFor);
  76. inNthen--;
  77. calls = (calls || 1) - 1;
  78. while (!calls && funcs.length) { callNext(waitFor); }
  79. }, milliseconds);
  80. funcs.push(cto = function() {
  81. var idx = timeouts.indexOf(timeout);
  82. if (idx > -1) {
  83. timeouts.splice(idx, 1);
  84. clearTimeout(timeout);
  85. return;
  86. }
  87. throw new Error('timeout not listed in array');
  88. });
  89. timeouts.push(timeout);
  90. return ret;
  91. }
  92. };
  93. return ret.nThen(next);
  94. };
  95. if (typeof(module) !== 'undefined') { module.exports = nThen; }
  96. else if (typeof(window.define) === 'function' && window.define.amd) { window.define(function () { return nThen; }); }
  97. else { window.nThen = nThen; }
  98. /*:: return nThen; */
  99. })();