Commit ff6988cb authored by Tristan Cavelier's avatar Tristan Cavelier

Promise based forEach added to jIO.util

parent aeed7d0d
......@@ -413,3 +413,72 @@ function methodType(method) {
return 'unknown';
}
}
/**
* forEach(array, callback[, thisArg]): Promise
*
* It executes the provided `callback` once for each element of the array with
* an assigned value asynchronously. If the `callback` returns a promise, then
* the function will wait for its fulfillment before executing the next
* iteration.
*
* `callback` is invoked with three arguments:
*
* - the element value
* - the element index
* - the array being traversed
*
* If a `thisArg` parameter is provided to `forEach`, it will be passed to
* `callback` when invoked, for use as its `this` value. Otherwise, the value
* `undefined` will be passed for use as its `this` value.
*
* Unlike `Array.prototype.forEach`, you can stop the iteration by throwing
* something, or by doing a `cancel` to the returned promise if it is
* cancellable promise.
*
* Inspired by `Array.prototype.forEach` from Mozilla Developer Network.
*
* @param {Array} array The array to parse
* @param {Function} callback Function to execute for each element.
* @param {Any} [thisArg] Value to use as `this` when executing `callback`.
* @param {Promise} A new promise.
*/
function forEach(array, fn, thisArg) {
if (arguments.length === 0) {
throw new TypeError("missing argument 0 when calling function forEach");
}
if (!Array.isArray(array)) {
throw new TypeError(array + " is not an array");
}
if (arguments.length === 1) {
throw new TypeError("missing argument 1 when calling function forEach");
}
if (typeof fn !== "function") {
throw new TypeError(fn + " is not a function");
}
var cancelled, current_promise = RSVP.resolve();
return new RSVP.Promise(function (done, fail, notify) {
var i = 0;
function next() {
if (cancelled) {
fail(new Error("Cancelled"));
return;
}
if (i < array.length) {
current_promise =
current_promise.then(fn.bind(thisArg, array[i], i, array));
current_promise.then(next, fail, notify);
i += 1;
return;
}
done();
}
next();
}, function () {
cancelled = true;
if (typeof current_promise.cancel === "function") {
current_promise.cancel();
}
});
}
exports.util.forEach = forEach;
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