___do.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*******************************************************************************
  2. AToMPM - A Tool for Multi-Paradigm Modelling
  3. REF:: https://github.com/creationix/do (+ .setup/do.js.patch)
  4. Copyright (c) 2011 Raphael Mannadiar (raphael.mannadiar@mail.mcgill.ca)
  5. This file is part of AToMPM.
  6. AToMPM is free software: you can redistribute it and/or modify it under the
  7. terms of the GNU Lesser General Public License as published by the Free Software
  8. Foundation, either version 3 of the License, or (at your option) any later
  9. version.
  10. AToMPM is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  12. PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public License along
  14. with AToMPM. If not, see <http://www.gnu.org/licenses/>.
  15. *******************************************************************************/
  16. // Takes an array of actions and runs them all in parallel.
  17. // You can either pass in an array of actions, or several actions
  18. // as function arguments.
  19. // If you pass in an array, then the output will be an array of all the results
  20. // If you pass in separate arguments, then the output will have several arguments.
  21. exports.parallel = function parallel(actions) {
  22. if (!(Object.prototype.toString.call(actions) === '[object Array]')) {
  23. actions = Array.prototype.slice.call(arguments);
  24. var direct = true;
  25. }
  26. return function(callback, errback) {
  27. var results = [],
  28. counter = actions.length;
  29. actions.forEach(function (action, i) {
  30. action(function (result) {
  31. results[i] = result;
  32. counter--;
  33. if (counter <= 0) {
  34. if (direct) {
  35. callback.apply(null, results);
  36. } else {
  37. callback.call(null, results);
  38. }
  39. }
  40. }, errback);
  41. });
  42. }
  43. };
  44. // Chains together several actions feeding the output of the first to the
  45. // input of the second and the final output to the callback
  46. exports.chain = function chain(actions) {
  47. if (!(Object.prototype.toString.call(actions) === '[object Array]')) {
  48. actions = Array.prototype.slice.call(arguments);
  49. }
  50. return function(callback, errback) {
  51. var pos = 0;
  52. var length = actions.length;
  53. function loop(result) {
  54. pos++;
  55. if (pos >= length) {
  56. callback(result);
  57. } else {
  58. actions[pos](result)(loop, errback);
  59. }
  60. }
  61. actions[pos](loop, errback);
  62. }
  63. }
  64. // Takes an array and does an array map over it using the async callback `fn`
  65. // The signature of `fn` is `function fn(item, callback, errback)`
  66. exports.map = function map(array, fn) { return function (callback, errback) {
  67. var counter = array.length;
  68. var new_array = [];
  69. array.forEach(function (item, index) {
  70. var local_callback = function (result) {
  71. new_array[index] = result;
  72. counter--;
  73. if (counter <= 0) {
  74. new_array.length = array.length
  75. callback(new_array);
  76. }
  77. };
  78. var cont = fn(item, local_callback, errback);
  79. if (typeof cont === 'function') {
  80. cont(local_callback, errback);
  81. }
  82. });
  83. }}
  84. // Takes an array and does an array filter over it using the async callback `fn`
  85. // The signature of `fn` is `function fn(item, callback, errback)`
  86. exports.filter = function filter(array, fn) { return function (callback, errback) {
  87. var counter = array.length;
  88. var valid = {};
  89. array.forEach(function (item, index) {
  90. var local_callback = function (result) {
  91. valid[index] = result;
  92. counter--;
  93. if (counter <= 0) {
  94. var result = [];
  95. array.forEach(function (item, index) {
  96. if (valid[index]) {
  97. result.push(item);
  98. }
  99. });
  100. callback(result);
  101. }
  102. };
  103. var cont = fn(item, local_callback, errback);
  104. if (typeof cont === 'function') {
  105. cont(local_callback, errback);
  106. }
  107. });
  108. }}
  109. // Takes an array and does a combined filter and map over it. If the result
  110. // of an item is undefined, then it's filtered out, otherwise it's mapped in.
  111. // The signature of `fn` is `function fn(item, callback, errback)`
  112. exports.filterMap = function filterMap(array, fn) { return function (callback, errback) {
  113. var counter = array.length;
  114. var new_array = [];
  115. array.forEach(function (item, index) {
  116. var local_callback = function (result) {
  117. new_array[index] = result;
  118. counter--;
  119. if (counter <= 0) {
  120. new_array.length = array.length;
  121. callback(new_array.filter(function (item) {
  122. return typeof item !== 'undefined';
  123. }));
  124. }
  125. };
  126. var cont = fn(item, local_callback, errback);
  127. if (typeof cont === 'function') {
  128. cont(local_callback, errback);
  129. }
  130. });
  131. }};
  132. // Allows to group several callbacks.
  133. exports.combo = function combo(callback) {
  134. var items = 0,
  135. results = [];
  136. function add() {
  137. var id = items;
  138. items++;
  139. return function () {
  140. check(id, arguments);
  141. };
  142. }
  143. function check(id, arguments) {
  144. results[id] = Array.prototype.slice.call(arguments);
  145. items--;
  146. if (items == 0) {
  147. callback.apply(this, results);
  148. }
  149. }
  150. return { add: add, check: check };
  151. }
  152. // Takes any async lib that uses callback based signatures and converts
  153. // the specified names to continuable style and returns the new library.
  154. exports.convert = function (lib, names) {
  155. var newlib = {};
  156. Object.keys(lib).forEach(function (key) {
  157. if (names.indexOf(key) < 0) {
  158. return newlib[key] = lib[key];
  159. }
  160. newlib[key] = function () {
  161. var args = Array.prototype.slice.call(arguments);
  162. return function (callback, errback) {
  163. args.push(function (err, val) {
  164. if (err) {
  165. errback(err);
  166. } else {
  167. callback(val);
  168. }
  169. });
  170. lib[key].apply(lib, args)
  171. }
  172. }
  173. });
  174. return newlib;
  175. }