Commit c0b1a7fd authored by Tristan Cavelier's avatar Tristan Cavelier

improve async foreach performance

parent 2fe53871
...@@ -496,41 +496,52 @@ function methodType(method) { ...@@ -496,41 +496,52 @@ function methodType(method) {
* @param {Any} [thisArg] Value to use as `this` when executing `callback`. * @param {Any} [thisArg] Value to use as `this` when executing `callback`.
* @param {Promise} A new promise. * @param {Promise} A new promise.
*/ */
function forEach(array, fn, thisArg) { function forEach(array, callback, thisArg) {
if (arguments.length === 0) { if (arguments.length === 0) {
throw new TypeError("missing argument 0 when calling function forEach"); throw new TypeError("forEach(): missing argument 1");
} }
if (!Array.isArray(array)) { if (!Array.isArray(array)) {
throw new TypeError(array + " is not an array"); throw new TypeError("forEach(): argument 1 is not an array");
} }
if (arguments.length === 1) { if (arguments.length === 1) {
throw new TypeError("missing argument 1 when calling function forEach"); throw new TypeError("forEach(): missing argument 2");
} }
if (typeof fn !== "function") { if (typeof callback !== "function") {
throw new TypeError(fn + " is not a function"); throw new TypeError("forEach(): argument 2 is not a function");
} }
var cancelled, current_promise = RSVP.resolve(); var cancelled, p1 = RSVP.resolve(), p2;
return new RSVP.Promise(function (done, fail, notify) { return new RSVP.Promise(function (done, fail, notify) {
var i = 0; var i = 0, value;
function next() { function next() {
if (cancelled) { // if cancelled before `next` execution, `next` should not be called
fail(new Error("Cancelled"));
return;
}
if (i < array.length) { if (i < array.length) {
current_promise = try {
current_promise.then(fn.bind(thisArg, array[i], i, array)); value = callback.call(thisArg, array[i], i, array);
current_promise.then(next, fail, notify); } catch (e) {
fail(e);
return;
}
// can be cancelled during callback
if (cancelled) { return; }
i += 1; i += 1;
if (value && typeof value.then === "function") {
p1 = value;
p2 = value.then(next, fail, notify);
} else {
p2 = p2.then(next, fail, notify);
}
return; return;
} }
done(); done();
} }
next(); p2 = p1.then(next);
}, function () { }, function () {
cancelled = true; cancelled = true;
if (typeof current_promise.cancel === "function") { if (typeof p1.cancel === "function") {
current_promise.cancel(); p1.cancel();
}
if (typeof p2.cancel === "function") {
p2.cancel();
} }
}); });
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment