Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

queue.js 8.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = queue;
  6. var _onlyOnce = require('./onlyOnce');
  7. var _onlyOnce2 = _interopRequireDefault(_onlyOnce);
  8. var _setImmediate = require('./setImmediate');
  9. var _setImmediate2 = _interopRequireDefault(_setImmediate);
  10. var _DoublyLinkedList = require('./DoublyLinkedList');
  11. var _DoublyLinkedList2 = _interopRequireDefault(_DoublyLinkedList);
  12. var _wrapAsync = require('./wrapAsync');
  13. var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
  14. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  15. function queue(worker, concurrency, payload) {
  16. if (concurrency == null) {
  17. concurrency = 1;
  18. } else if (concurrency === 0) {
  19. throw new RangeError('Concurrency must not be zero');
  20. }
  21. var _worker = (0, _wrapAsync2.default)(worker);
  22. var numRunning = 0;
  23. var workersList = [];
  24. const events = {
  25. error: [],
  26. drain: [],
  27. saturated: [],
  28. unsaturated: [],
  29. empty: []
  30. };
  31. function on(event, handler) {
  32. events[event].push(handler);
  33. }
  34. function once(event, handler) {
  35. const handleAndRemove = (...args) => {
  36. off(event, handleAndRemove);
  37. handler(...args);
  38. };
  39. events[event].push(handleAndRemove);
  40. }
  41. function off(event, handler) {
  42. if (!event) return Object.keys(events).forEach(ev => events[ev] = []);
  43. if (!handler) return events[event] = [];
  44. events[event] = events[event].filter(ev => ev !== handler);
  45. }
  46. function trigger(event, ...args) {
  47. events[event].forEach(handler => handler(...args));
  48. }
  49. var processingScheduled = false;
  50. function _insert(data, insertAtFront, rejectOnError, callback) {
  51. if (callback != null && typeof callback !== 'function') {
  52. throw new Error('task callback must be a function');
  53. }
  54. q.started = true;
  55. var res, rej;
  56. function promiseCallback(err, ...args) {
  57. // we don't care about the error, let the global error handler
  58. // deal with it
  59. if (err) return rejectOnError ? rej(err) : res();
  60. if (args.length <= 1) return res(args[0]);
  61. res(args);
  62. }
  63. var item = {
  64. data,
  65. callback: rejectOnError ? promiseCallback : callback || promiseCallback
  66. };
  67. if (insertAtFront) {
  68. q._tasks.unshift(item);
  69. } else {
  70. q._tasks.push(item);
  71. }
  72. if (!processingScheduled) {
  73. processingScheduled = true;
  74. (0, _setImmediate2.default)(() => {
  75. processingScheduled = false;
  76. q.process();
  77. });
  78. }
  79. if (rejectOnError || !callback) {
  80. return new Promise((resolve, reject) => {
  81. res = resolve;
  82. rej = reject;
  83. });
  84. }
  85. }
  86. function _createCB(tasks) {
  87. return function (err, ...args) {
  88. numRunning -= 1;
  89. for (var i = 0, l = tasks.length; i < l; i++) {
  90. var task = tasks[i];
  91. var index = workersList.indexOf(task);
  92. if (index === 0) {
  93. workersList.shift();
  94. } else if (index > 0) {
  95. workersList.splice(index, 1);
  96. }
  97. task.callback(err, ...args);
  98. if (err != null) {
  99. trigger('error', err, task.data);
  100. }
  101. }
  102. if (numRunning <= q.concurrency - q.buffer) {
  103. trigger('unsaturated');
  104. }
  105. if (q.idle()) {
  106. trigger('drain');
  107. }
  108. q.process();
  109. };
  110. }
  111. function _maybeDrain(data) {
  112. if (data.length === 0 && q.idle()) {
  113. // call drain immediately if there are no tasks
  114. (0, _setImmediate2.default)(() => trigger('drain'));
  115. return true;
  116. }
  117. return false;
  118. }
  119. const eventMethod = name => handler => {
  120. if (!handler) {
  121. return new Promise((resolve, reject) => {
  122. once(name, (err, data) => {
  123. if (err) return reject(err);
  124. resolve(data);
  125. });
  126. });
  127. }
  128. off(name);
  129. on(name, handler);
  130. };
  131. var isProcessing = false;
  132. var q = {
  133. _tasks: new _DoublyLinkedList2.default(),
  134. *[Symbol.iterator]() {
  135. yield* q._tasks[Symbol.iterator]();
  136. },
  137. concurrency,
  138. payload,
  139. buffer: concurrency / 4,
  140. started: false,
  141. paused: false,
  142. push(data, callback) {
  143. if (Array.isArray(data)) {
  144. if (_maybeDrain(data)) return;
  145. return data.map(datum => _insert(datum, false, false, callback));
  146. }
  147. return _insert(data, false, false, callback);
  148. },
  149. pushAsync(data, callback) {
  150. if (Array.isArray(data)) {
  151. if (_maybeDrain(data)) return;
  152. return data.map(datum => _insert(datum, false, true, callback));
  153. }
  154. return _insert(data, false, true, callback);
  155. },
  156. kill() {
  157. off();
  158. q._tasks.empty();
  159. },
  160. unshift(data, callback) {
  161. if (Array.isArray(data)) {
  162. if (_maybeDrain(data)) return;
  163. return data.map(datum => _insert(datum, true, false, callback));
  164. }
  165. return _insert(data, true, false, callback);
  166. },
  167. unshiftAsync(data, callback) {
  168. if (Array.isArray(data)) {
  169. if (_maybeDrain(data)) return;
  170. return data.map(datum => _insert(datum, true, true, callback));
  171. }
  172. return _insert(data, true, true, callback);
  173. },
  174. remove(testFn) {
  175. q._tasks.remove(testFn);
  176. },
  177. process() {
  178. // Avoid trying to start too many processing operations. This can occur
  179. // when callbacks resolve synchronously (#1267).
  180. if (isProcessing) {
  181. return;
  182. }
  183. isProcessing = true;
  184. while (!q.paused && numRunning < q.concurrency && q._tasks.length) {
  185. var tasks = [],
  186. data = [];
  187. var l = q._tasks.length;
  188. if (q.payload) l = Math.min(l, q.payload);
  189. for (var i = 0; i < l; i++) {
  190. var node = q._tasks.shift();
  191. tasks.push(node);
  192. workersList.push(node);
  193. data.push(node.data);
  194. }
  195. numRunning += 1;
  196. if (q._tasks.length === 0) {
  197. trigger('empty');
  198. }
  199. if (numRunning === q.concurrency) {
  200. trigger('saturated');
  201. }
  202. var cb = (0, _onlyOnce2.default)(_createCB(tasks));
  203. _worker(data, cb);
  204. }
  205. isProcessing = false;
  206. },
  207. length() {
  208. return q._tasks.length;
  209. },
  210. running() {
  211. return numRunning;
  212. },
  213. workersList() {
  214. return workersList;
  215. },
  216. idle() {
  217. return q._tasks.length + numRunning === 0;
  218. },
  219. pause() {
  220. q.paused = true;
  221. },
  222. resume() {
  223. if (q.paused === false) {
  224. return;
  225. }
  226. q.paused = false;
  227. (0, _setImmediate2.default)(q.process);
  228. }
  229. };
  230. // define these as fixed properties, so people get useful errors when updating
  231. Object.defineProperties(q, {
  232. saturated: {
  233. writable: false,
  234. value: eventMethod('saturated')
  235. },
  236. unsaturated: {
  237. writable: false,
  238. value: eventMethod('unsaturated')
  239. },
  240. empty: {
  241. writable: false,
  242. value: eventMethod('empty')
  243. },
  244. drain: {
  245. writable: false,
  246. value: eventMethod('drain')
  247. },
  248. error: {
  249. writable: false,
  250. value: eventMethod('error')
  251. }
  252. });
  253. return q;
  254. }
  255. module.exports = exports['default'];