v5.x
This commit is contained in:
parent
0cc859e3d0
commit
c543917f07
89
README.md
89
README.md
|
@ -5,45 +5,45 @@ Analogous to `[].forEach`, but handles items asynchronously with a final callbac
|
|||
|
||||
This is the most essential piece of the [`ArrayAsync`](https://github.com/FuturesJS/ArrayAsync) package.
|
||||
|
||||
v3.x - Diet Cola Edition
|
||||
---
|
||||
|
||||
As I do every few years, I decided to rewrite FuturesJS.
|
||||
This year's remake is extremely lightweight.
|
||||
v5.x
|
||||
----
|
||||
|
||||
We jumped from 3.x to 5.x because I'm considering creating a backwards-and-forwards compatible 4.x that
|
||||
uses AngularJS-style function introspection to allow for having the next param.
|
||||
Straight up, that's probably a bad idea and waste of time so I hope I don't actually do it.
|
||||
|
||||
Usage
|
||||
===
|
||||
|
||||
It's as simple as you could guess:
|
||||
-----
|
||||
|
||||
```javascript
|
||||
// waits for one request to finish before beginning the next
|
||||
forEachAsync(['dogs', 'cats', 'octocats'], function (next, element, index, array) {
|
||||
getPics(element, next);
|
||||
|
||||
// then after all of the elements have been handled
|
||||
// the final callback fires to let you know it's all done
|
||||
}).then(function () {
|
||||
console.log('All requests have finished');
|
||||
});
|
||||
// EXAMPLE ASYNC FUNCTION
|
||||
|
||||
// where `getPics` might be an asynchronous web request such as this
|
||||
function getPics(animal, cb) {
|
||||
var flickerAPI = "http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?";
|
||||
$.getJSON(
|
||||
flickerAPI
|
||||
, { tags: thing
|
||||
, tagmode: "any"
|
||||
, format: "json"
|
||||
, success: function (data) {
|
||||
console.log('teh animals:', data);
|
||||
}
|
||||
, complete: cb
|
||||
}
|
||||
);
|
||||
function getPicsAsync(animal) {
|
||||
var flickerApi = "http://api.flickr.com/services/feeds/photos_public.gne?tagmode=any&format=json&tags=" + animal;
|
||||
|
||||
return requestAsync({ url: flickerApi });
|
||||
}
|
||||
```
|
||||
|
||||
```javascript
|
||||
forEachAsync(['dogs', 'cats', 'octocats'], function (element) {
|
||||
return getPicsAsync(element);
|
||||
}).then(function () {
|
||||
// then after all of the elements have been handled
|
||||
// the final callback fires to let you know it's all done
|
||||
console.log('All requests have finished');
|
||||
});
|
||||
```
|
||||
|
||||
### Supplying your own Promises Implementation
|
||||
|
||||
If native ES6 promises are not available, then you should supply your own Promises/A+
|
||||
implementation like so:
|
||||
|
||||
```javascript
|
||||
forEachAsync = forEachAsync.create(window.Promise || require('bluebird'));
|
||||
```
|
||||
|
||||
Browser Installation
|
||||
===
|
||||
|
@ -51,7 +51,7 @@ Browser Installation
|
|||
You can install from bower:
|
||||
|
||||
```bash
|
||||
bower install forEachAsync
|
||||
bower install --save forEachAsync@5.x
|
||||
```
|
||||
|
||||
Or download the raw file from <https://raw.github.com/FuturesJS/forEachAsync/master/forEachAsync.js>:
|
||||
|
@ -71,35 +71,13 @@ wget https://raw.github.com/FuturesJS/forEachAsync/master/forEachAsync.js
|
|||
}());
|
||||
```
|
||||
|
||||
Or you can build it alongside other libraries:
|
||||
|
||||
```bash
|
||||
npm install -g pakmanager
|
||||
npm install forEachAsync --save
|
||||
pakmanager -e browser build
|
||||
```
|
||||
|
||||
```html
|
||||
<script src="pakmanaged.js"></script>
|
||||
```
|
||||
|
||||
```javascript
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var forEachAsync = require('forEachAsync').forEachAsync
|
||||
;
|
||||
|
||||
// do stuff ...
|
||||
}());
|
||||
```
|
||||
|
||||
**Note**: If you need both 3.x/4.x and 5.x version of `forEachAsync` in the browser... good luck with that...
|
||||
|
||||
Node Installation
|
||||
===
|
||||
|
||||
```bash
|
||||
npm install --save forEachAsync@3.x
|
||||
npm install --save forEachAsync@5.x
|
||||
```
|
||||
|
||||
API
|
||||
|
@ -111,7 +89,6 @@ Parameters
|
|||
|
||||
* `array` Array of elements to iterate over
|
||||
* `callback` Function to execute for each element, takes 4 arguments
|
||||
* `next` the function to call when the current element has been dealt with
|
||||
* `element` a single element of the aforementioned array
|
||||
* `index` the index of the current element
|
||||
* `array` the same array mentioned above
|
||||
|
|
|
@ -11,14 +11,16 @@ window.addEventListener('load', function () {
|
|||
;
|
||||
|
||||
log('i', 'item', 'ms');
|
||||
forEachAsync([2, 11, 37, 42], function (next, item, i) {
|
||||
forEachAsync([2, 11, 37, 42], function (item, i) {
|
||||
var ms = Math.floor(Math.random() * 1000)
|
||||
;
|
||||
|
||||
setTimeout(function () {
|
||||
log(i, item, ms);
|
||||
next();
|
||||
}, ms);
|
||||
return new Promise(function (resolve) {
|
||||
setTimeout(function () {
|
||||
log(i, item, ms);
|
||||
resolve();
|
||||
}, ms);
|
||||
});
|
||||
}).then(function () {
|
||||
log('All Done');
|
||||
});
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
'use strict';
|
||||
|
||||
var fs = require('fs')
|
||||
var PromiseA = require('bluebird')
|
||||
, fs = PromiseA.promisifyAll(require('fs'))
|
||||
, forEachAsync = require('foreachasync').forEachAsync
|
||||
, path = require('path')
|
||||
, dirpath = path.join(__dirname, 'testfiles')
|
||||
;
|
||||
|
||||
fs.readdir(dirpath, function (err, nodes) {
|
||||
forEachAsync(nodes, function (next, node) {
|
||||
forEachAsync(nodes, function (node) {
|
||||
var filepath = path.join(dirpath, node)
|
||||
;
|
||||
|
||||
console.log(filepath);
|
||||
fs.readFile(filepath, null, function (err, contents) {
|
||||
return fs.readFileAsync(filepath, null).then(function (contents) {
|
||||
console.log(node, contents.length);
|
||||
next();
|
||||
});
|
||||
}).then(function () {
|
||||
console.log('All Done!');
|
||||
|
|
|
@ -2,34 +2,89 @@
|
|||
;(function (exports) {
|
||||
'use strict';
|
||||
|
||||
function forEachAsync(arr, fn, thisArg) {
|
||||
var dones = []
|
||||
, index = -1
|
||||
;
|
||||
var BREAK = {}
|
||||
, exp = {}
|
||||
;
|
||||
|
||||
function next(BREAK, result) {
|
||||
index += 1;
|
||||
function create(PromiseA) {
|
||||
PromiseA = PromiseA.Promise || PromiseA;
|
||||
|
||||
if (index === arr.length || BREAK === forEachAsync.__BREAK) {
|
||||
dones.forEach(function (done) {
|
||||
done.call(thisArg, result);
|
||||
|
||||
function forEachAsync(arr, fn, thisArg) {
|
||||
var result = PromiseA.resolve()
|
||||
;
|
||||
|
||||
arr.forEach(function (item, k) {
|
||||
result = result.then(function () {
|
||||
|
||||
var ret
|
||||
;
|
||||
|
||||
if (thisArg) {
|
||||
ret = fn.call(thisArg, item, k, arr);
|
||||
} else {
|
||||
ret = result = fn(item, k, arr);
|
||||
}
|
||||
|
||||
if (!ret.then) {
|
||||
ret = PromiseA.resolve(result);
|
||||
}
|
||||
|
||||
ret.then(function (val) {
|
||||
if (val === forEachAsync.__BREAK) {
|
||||
return PromiseA.reject(new Error('break'));
|
||||
//throw new Error('break');
|
||||
}
|
||||
|
||||
return val;
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
fn.call(thisArg, next, arr[index], index, arr);
|
||||
result.catch(function (e) {
|
||||
if ('break' !== e.message) {
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
setTimeout(next, 4);
|
||||
forEachAsync.__BREAK = BREAK;
|
||||
|
||||
return {
|
||||
then: function (_done) {
|
||||
dones.push(_done);
|
||||
return this;
|
||||
}
|
||||
};
|
||||
return forEachAsync;
|
||||
}
|
||||
forEachAsync.__BREAK = {};
|
||||
|
||||
exports.forEachAsync = forEachAsync;
|
||||
/*
|
||||
exp = forEachAsync.forEachAsync = forEachAsync;
|
||||
exports = exports.forEachAsync = forEachAsync.forEachAsycn = forEachAsync;
|
||||
exports.create = forEachAsync.create = function () {};
|
||||
*/
|
||||
|
||||
|
||||
try {
|
||||
exp.forEachAsync = create(require('bluebird'));
|
||||
} catch(e) {
|
||||
if ('undefined' !== typeof PromiseA) {
|
||||
exp.forEachAsync = create(Promise);
|
||||
} else {
|
||||
try {
|
||||
exp.forEachAsync = create(require('es6-promise'));
|
||||
} catch(e) {
|
||||
try {
|
||||
exp.forEachAsync = create(require('rsvp'));
|
||||
} catch(e) {
|
||||
console.warning('forEachAsync needs requires a promise implementation and your environment does not provide one.'
|
||||
+ '\nYou may provide your own by calling forEachAsync.create(Promise) with a PromiseA+ implementation'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.forEachAsync = exp.forEachAsync.forEachAsync = exp.forEachAsync || function () {
|
||||
throw new Error("You did not supply a Promises/A+ implementation. See the warning above.");
|
||||
};
|
||||
exports.forEachAsync.create = create;
|
||||
|
||||
}('undefined' !== typeof exports && exports || new Function('return this')()));
|
||||
|
|
11
package.json
11
package.json
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "foreachasync",
|
||||
"version": "3.0.0",
|
||||
"description": "A node- and browser-ready async counterpart of Array.prototype.forEach",
|
||||
"version": "5.0.0",
|
||||
"description": "A node- and browser-ready async (now with promises) counterpart of Array.prototype.forEach",
|
||||
"homepage": "https://github.com/FuturesJS/forEachAsync",
|
||||
"main": "forEachAsync.js",
|
||||
"directories": {
|
||||
|
@ -21,11 +21,18 @@
|
|||
"forEachAsync",
|
||||
"async",
|
||||
"futures",
|
||||
"promise",
|
||||
"promises",
|
||||
"each"
|
||||
],
|
||||
"optionalDependencies": {
|
||||
"bluebird": "^2.5.3"
|
||||
},
|
||||
"author": "AJ ONeal <coolaj86@gmail.com> (http://coolaj86.com/)",
|
||||
"license": "Apache2",
|
||||
"bugs": {
|
||||
"url": "https://github.com/FuturesJS/forEachAsync/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
(function () {
|
||||
"use strict";
|
||||
|
||||
var PromiseA = require('bluebird')
|
||||
, forEachAsync = require('./forEachAsync').forEachAsync
|
||||
, context = {}
|
||||
;
|
||||
|
||||
forEachAsync([0, 500, 70, 200, 400, 100], function (element, i, arr) {
|
||||
// test that array order is as expected
|
||||
console.log(element, 'is element', i, 'of', arr.length);
|
||||
|
||||
// test that thisness is applied
|
||||
this[element] = i;
|
||||
|
||||
if (i > 2) {
|
||||
// test that synchronous callbacks don't mess things up
|
||||
return PromiseA.resolve();
|
||||
} else {
|
||||
// test asynchronous callbacks
|
||||
return new Promise(function (resolve/*, reject*/) {
|
||||
setTimeout(resolve, element);
|
||||
});
|
||||
}
|
||||
}, context).then(function () {
|
||||
// test that thisness carried
|
||||
console.log('context', context);
|
||||
}).then(function () {
|
||||
// test then chaining
|
||||
console.log("now wasn't that nice?");
|
||||
});
|
||||
}());
|
|
@ -1,10 +1,11 @@
|
|||
(function () {
|
||||
"use strict";
|
||||
|
||||
var forEachAsync = require('./forEachAsync').forEachAsync
|
||||
var forEachAsync = require('./forEachAsync').forEachAsync.create(Promise)
|
||||
, context = {}
|
||||
;
|
||||
|
||||
forEachAsync([0, 500, 70, 200, 400, 100], function (next, element, i, arr) {
|
||||
forEachAsync([0, 500, 70, 200, 400, 100], function (element, i, arr) {
|
||||
// test that array order is as expected
|
||||
console.log(element, 'is element', i, 'of', arr.length);
|
||||
|
||||
|
@ -13,17 +14,18 @@
|
|||
|
||||
if (i > 2) {
|
||||
// test that synchronous callbacks don't mess things up
|
||||
next();
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
// test asynchronous callbacks
|
||||
setTimeout(next, element);
|
||||
return new Promise(function (resolve/*, reject*/) {
|
||||
setTimeout(resolve, element);
|
||||
});
|
||||
}
|
||||
}, {}).then(function () {
|
||||
// test that thisness carries
|
||||
console.log(this);
|
||||
}, context).then(function () {
|
||||
// test that thisness carried
|
||||
console.log('context', context);
|
||||
}).then(function () {
|
||||
// test then chaining
|
||||
console.log("now wasn't that nice?");
|
||||
});
|
||||
|
||||
}());
|
Loading…
Reference in New Issue