ad12b6db7191f54787035471f55817149013f8f7
[tech-radar.git] / examples / d3-queue.js
1 // https://d3js.org/d3-queue/ Version 3.0.5. Copyright 2017 Mike Bostock.
2 (function (global, factory) {
3 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
4 typeof define === 'function' && define.amd ? define(['exports'], factory) :
5 (factory((global.d3 = global.d3 || {})));
6 }(this, (function (exports) { 'use strict';
7
8 var slice = [].slice;
9
10 var noabort = {};
11
12 function Queue(size) {
13 if (!(size >= 1)) throw new Error;
14 this._size = size;
15 this._call =
16 this._error = null;
17 this._tasks = [];
18 this._data = [];
19 this._waiting =
20 this._active =
21 this._ended =
22 this._start = 0; // inside a synchronous task callback?
23 }
24
25 Queue.prototype = queue.prototype = {
26 constructor: Queue,
27 defer: function(callback) {
28 if (typeof callback !== "function" || this._call) throw new Error;
29 if (this._error != null) return this;
30 var t = slice.call(arguments, 1);
31 t.push(callback);
32 ++this._waiting, this._tasks.push(t);
33 poke(this);
34 return this;
35 },
36 abort: function() {
37 if (this._error == null) abort(this, new Error("abort"));
38 return this;
39 },
40 await: function(callback) {
41 if (typeof callback !== "function" || this._call) throw new Error;
42 this._call = function(error, results) { callback.apply(null, [error].concat(results)); };
43 maybeNotify(this);
44 return this;
45 },
46 awaitAll: function(callback) {
47 if (typeof callback !== "function" || this._call) throw new Error;
48 this._call = callback;
49 maybeNotify(this);
50 return this;
51 }
52 };
53
54 function poke(q) {
55 if (!q._start) {
56 try { start(q); } // let the current task complete
57 catch (e) {
58 if (q._tasks[q._ended + q._active - 1]) abort(q, e); // task errored synchronously
59 else if (!q._data) throw e; // await callback errored synchronously
60 }
61 }
62 }
63
64 function start(q) {
65 while (q._start = q._waiting && q._active < q._size) {
66 var i = q._ended + q._active,
67 t = q._tasks[i],
68 j = t.length - 1,
69 c = t[j];
70 t[j] = end(q, i);
71 --q._waiting, ++q._active;
72 t = c.apply(null, t);
73 if (!q._tasks[i]) continue; // task finished synchronously
74 q._tasks[i] = t || noabort;
75 }
76 }
77
78 function end(q, i) {
79 return function(e, r) {
80 if (!q._tasks[i]) return; // ignore multiple callbacks
81 --q._active, ++q._ended;
82 q._tasks[i] = null;
83 if (q._error != null) return; // ignore secondary errors
84 if (e != null) {
85 abort(q, e);
86 } else {
87 q._data[i] = r;
88 if (q._waiting) poke(q);
89 else maybeNotify(q);
90 }
91 };
92 }
93
94 function abort(q, e) {
95 var i = q._tasks.length, t;
96 q._error = e; // ignore active callbacks
97 q._data = undefined; // allow gc
98 q._waiting = NaN; // prevent starting
99
100 while (--i >= 0) {
101 if (t = q._tasks[i]) {
102 q._tasks[i] = null;
103 if (t.abort) {
104 try { t.abort(); }
105 catch (e) { /* ignore */ }
106 }
107 }
108 }
109
110 q._active = NaN; // allow notification
111 maybeNotify(q);
112 }
113
114 function maybeNotify(q) {
115 if (!q._active && q._call) {
116 var d = q._data;
117 q._data = undefined; // allow gc
118 q._call(q._error, d);
119 }
120 }
121
122 function queue(concurrency) {
123 return new Queue(arguments.length ? +concurrency : Infinity);
124 }
125
126 exports.queue = queue;
127
128 Object.defineProperty(exports, '__esModule', { value: true });
129
130 })));