Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
81160 views
1
"use strict";
2
module.exports = function(Promise,
3
PromiseArray,
4
apiRejection,
5
tryConvertToPromise,
6
INTERNAL) {
7
var async = require("./async.js");
8
var util = require("./util.js");
9
var tryCatch = util.tryCatch;
10
var errorObj = util.errorObj;
11
var PENDING = {};
12
var EMPTY_ARRAY = [];
13
14
function MappingPromiseArray(promises, fn, limit, _filter) {
15
this.constructor$(promises);
16
this._promise._captureStackTrace();
17
this._callback = fn;
18
this._preservedValues = _filter === INTERNAL
19
? new Array(this.length())
20
: null;
21
this._limit = limit;
22
this._inFlight = 0;
23
this._queue = limit >= 1 ? [] : EMPTY_ARRAY;
24
async.invoke(init, this, undefined);
25
}
26
util.inherits(MappingPromiseArray, PromiseArray);
27
function init() {this._init$(undefined, -2);}
28
29
MappingPromiseArray.prototype._init = function () {};
30
31
MappingPromiseArray.prototype._promiseFulfilled = function (value, index) {
32
var values = this._values;
33
var length = this.length();
34
var preservedValues = this._preservedValues;
35
var limit = this._limit;
36
if (values[index] === PENDING) {
37
values[index] = value;
38
if (limit >= 1) {
39
this._inFlight--;
40
this._drainQueue();
41
if (this._isResolved()) return;
42
}
43
} else {
44
if (limit >= 1 && this._inFlight >= limit) {
45
values[index] = value;
46
this._queue.push(index);
47
return;
48
}
49
if (preservedValues !== null) preservedValues[index] = value;
50
51
var callback = this._callback;
52
var receiver = this._promise._boundTo;
53
this._promise._pushContext();
54
var ret = tryCatch(callback).call(receiver, value, index, length);
55
this._promise._popContext();
56
if (ret === errorObj) return this._reject(ret.e);
57
58
var maybePromise = tryConvertToPromise(ret, this._promise);
59
if (maybePromise instanceof Promise) {
60
maybePromise = maybePromise._target();
61
if (maybePromise._isPending()) {
62
if (limit >= 1) this._inFlight++;
63
values[index] = PENDING;
64
return maybePromise._proxyPromiseArray(this, index);
65
} else if (maybePromise._isFulfilled()) {
66
ret = maybePromise._value();
67
} else {
68
return this._reject(maybePromise._reason());
69
}
70
}
71
values[index] = ret;
72
}
73
var totalResolved = ++this._totalResolved;
74
if (totalResolved >= length) {
75
if (preservedValues !== null) {
76
this._filter(values, preservedValues);
77
} else {
78
this._resolve(values);
79
}
80
81
}
82
};
83
84
MappingPromiseArray.prototype._drainQueue = function () {
85
var queue = this._queue;
86
var limit = this._limit;
87
var values = this._values;
88
while (queue.length > 0 && this._inFlight < limit) {
89
if (this._isResolved()) return;
90
var index = queue.pop();
91
this._promiseFulfilled(values[index], index);
92
}
93
};
94
95
MappingPromiseArray.prototype._filter = function (booleans, values) {
96
var len = values.length;
97
var ret = new Array(len);
98
var j = 0;
99
for (var i = 0; i < len; ++i) {
100
if (booleans[i]) ret[j++] = values[i];
101
}
102
ret.length = j;
103
this._resolve(ret);
104
};
105
106
MappingPromiseArray.prototype.preservedValues = function () {
107
return this._preservedValues;
108
};
109
110
function map(promises, fn, options, _filter) {
111
var limit = typeof options === "object" && options !== null
112
? options.concurrency
113
: 0;
114
limit = typeof limit === "number" &&
115
isFinite(limit) && limit >= 1 ? limit : 0;
116
return new MappingPromiseArray(promises, fn, limit, _filter);
117
}
118
119
Promise.prototype.map = function (fn, options) {
120
if (typeof fn !== "function") return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a");
121
122
return map(this, fn, options, null).promise();
123
};
124
125
Promise.map = function (promises, fn, options, _filter) {
126
if (typeof fn !== "function") return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a");
127
return map(promises, fn, options, _filter).promise();
128
};
129
130
131
};
132
133