├── .gitignore
├── .jshintrc
├── .travis.yml
├── README.md
├── index.js
├── package.json
└── test
├── arrays.js
└── mocha.opts
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 |
19 | # node-waf configuration
20 | .lock-wscript
21 |
22 | # Compiled binary addons (http://nodejs.org/api/addons.html)
23 | build/Release
24 |
25 | # Dependency directory
26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
27 | node_modules
28 |
29 | # Idea
30 | .idea
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | // --------------------------------------------------------------------
3 | // JSHint Configuration, Strict Edition
4 | // --------------------------------------------------------------------
5 | //
6 | // This is a options template for [JSHint][1], using [JSHint example][2]
7 | // and [Ory Band's example][3] as basis and setting config values to
8 | // be most strict:
9 | //
10 | // * set all enforcing options to true
11 | // * set all relaxing options to false
12 | // * set all environment options to false, except the browser value
13 | // * set all JSLint legacy options to false
14 | //
15 | // [1]: http://www.jshint.com/
16 | // [2]: https://github.com/jshint/node-jshint/blob/master/example/config.json
17 | // [3]: https://github.com/oryband/dotfiles/blob/master/jshintrc
18 | //
19 | // @author http://michael.haschke.biz/
20 | // @license http://unlicense.org/
21 |
22 | // == Enforcing Options ===============================================
23 | //
24 | // These options tell JSHint to be more strict towards your code. Use
25 | // them if you want to allow only a safe subset of JavaScript, very
26 | // useful when your codebase is shared with a big number of developers
27 | // with different skill levels.
28 |
29 | "bitwise" : true, // Prohibit bitwise operators (&, |, ^, etc.).
30 | "curly" : true, // Require {} for every new block or scope.
31 | "eqeqeq" : true, // Require triple equals i.e. `===`.
32 | "forin" : true, // Tolerate `for in` loops without `hasOwnPrototype`.
33 | "immed" : true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );`
34 | "latedef" : true, // Prohibit variable use before definition.
35 | "newcap" : true, // Require capitalization of all constructor functions e.g. `new F()`.
36 | "noarg" : true, // Prohibit use of `arguments.caller` and `arguments.callee`.
37 | "noempty" : true, // Prohibit use of empty blocks.
38 | "nonew" : true, // Prohibit use of constructors for side-effects.
39 | "plusplus" : true, // Prohibit use of `++` & `--`.
40 | "regexp" : true, // Prohibit `.` and `[^...]` in regular expressions.
41 | "undef" : true, // Require all non-global variables be declared before they are used.
42 | "strict" : true, // Require `use strict` pragma in every file.
43 | "trailing" : true, // Prohibit trailing whitespaces.
44 |
45 | // == Relaxing Options ================================================
46 | //
47 | // These options allow you to suppress certain types of warnings. Use
48 | // them only if you are absolutely positive that you know what you are
49 | // doing.
50 |
51 | "asi" : false, // Tolerate Automatic Semicolon Insertion (no semicolons).
52 | "boss" : false, // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments.
53 | "debug" : false, // Allow debugger statements e.g. browser breakpoints.
54 | "eqnull" : false, // Tolerate use of `== null`.
55 | "es5" : false, // Allow EcmaScript 5 syntax.
56 | "esnext" : false, // Allow ES.next specific features such as `const` and `let`.
57 | "evil" : false, // Tolerate use of `eval`.
58 | "expr" : false, // Tolerate `ExpressionStatement` as Programs.
59 | "funcscope" : false, // Tolerate declarations of variables inside of control structures while accessing them later from the outside.
60 | "globalstrict" : false, // Allow global "use strict" (also enables 'strict').
61 | "iterator" : false, // Allow usage of __iterator__ property.
62 | "lastsemic" : false, // Tolerat missing semicolons when the it is omitted for the last statement in a one-line block.
63 | "laxbreak" : false, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons.
64 | "laxcomma" : false, // Suppress warnings about comma-first coding style.
65 | "loopfunc" : false, // Allow functions to be defined within loops.
66 | "multistr" : false, // Tolerate multi-line strings.
67 | "onecase" : false, // Tolerate switches with just one case.
68 | "proto" : false, // Tolerate __proto__ property. This property is deprecated.
69 | "regexdash" : false, // Tolerate unescaped last dash i.e. `[-...]`.
70 | "scripturl" : false, // Tolerate script-targeted URLs.
71 | "smarttabs" : false, // Tolerate mixed tabs and spaces when the latter are used for alignmnent only.
72 | "shadow" : false, // Allows re-define variables later in code e.g. `var x=1; x=2;`.
73 | "sub" : false, // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`.
74 | "supernew" : false, // Tolerate `new function () { ... };` and `new Object;`.
75 | "validthis" : false, // Tolerate strict violations when the code is running in strict mode and you use this in a non-constructor function.
76 |
77 | // == Environments ====================================================
78 | //
79 | // These options pre-define global variables that are exposed by
80 | // popular JavaScript libraries and runtime environments—such as
81 | // browser or node.js.
82 |
83 | "browser" : true, // Standard browser globals e.g. `window`, `document`.
84 | "couch" : false, // Enable globals exposed by CouchDB.
85 | "devel" : true, // Allow development statements e.g. `console.log();`.
86 | "dojo" : false, // Enable globals exposed by Dojo Toolkit.
87 | "jquery" : false, // Enable globals exposed by jQuery JavaScript library.
88 | "mootools" : false, // Enable globals exposed by MooTools JavaScript framework.
89 | "node" : true, // Enable globals available when code is running inside of the NodeJS runtime environment.
90 | "nonstandard" : false, // Define non-standard but widely adopted globals such as escape and unescape.
91 | "prototypejs" : false, // Enable globals exposed by Prototype JavaScript framework.
92 | "rhino" : false, // Enable globals available when your code is running inside of the Rhino runtime environment.
93 | "wsh" : false, // Enable globals available when your code is running as a script for the Windows Script Host.
94 |
95 | // == JSLint Legacy ===================================================
96 | //
97 | // These options are legacy from JSLint. Aside from bug fixes they will
98 | // not be improved in any way and might be removed at any point.
99 |
100 | "nomen" : false, // Prohibit use of initial or trailing underbars in names.
101 | "onevar" : false, // Allow only one `var` statement per function.
102 | "passfail" : false, // Stop on first error.
103 | "white" : false, // Check against strict whitespace and indentation rules.
104 |
105 | // == Undocumented Options ============================================
106 | //
107 | // While I've found these options in [example1][2] and [example2][3]
108 | // they are not described in the [JSHint Options documentation][4].
109 | //
110 | // [4]: http://www.jshint.com/options/
111 |
112 | "maxerr" : 100, // Maximum errors before stopping.
113 | "predef" : [ // Extra globals.
114 | "define"
115 | ],
116 | "indent" : 4 // Specify indentation spacing
117 | }
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "0.12"
4 | - "4.0"
5 | - "stable"
6 | - "iojs"
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Promise Arrays [![NPM version][npm-version-image]][npm-url] [![Travis Build][travis-build-image]][travis-url] [![MIT License][license-image]][license-url]
2 | ===
3 | A super small library to help you map and filter arrays with async operations. The only hard dependency is
4 | `Promise` so it needs to be present some how in your project (polyfill or native).
5 | Compatible with NodeJS, CommonJS, AMD and Browser Globals.
6 |
7 | ## Install
8 | Available on `npm`:
9 | ```bash
10 | $ npm install promise-arrays --save
11 | ```
12 |
13 | ### NodeJS
14 | Install using `npm` Then:
15 | ```javascript
16 | // ES5:
17 | var PromiseArrays = require('promise-arrays');
18 |
19 | // ES6:
20 | import PromiseArrays from 'promise-arrays';
21 | ```
22 |
23 | ### AMD
24 | Install `npm` and include in your AMD project, then:
25 | ```javascript
26 | // Include as dependency:
27 | define(['promise-arrays'], function (PromiseArrays) {
28 | // Use Here...
29 | });
30 | ```
31 |
32 | ### Browser Globals
33 | ```html
34 |
35 | ```
36 |
37 | ## Usage
38 | All methods in this library return a `Promise` object. The API is similar to JS native `filter` and `map`, although
39 | you can return a `Promise` instead of just returning the result.
40 |
41 | ### PromiseArrays.map(array, callback) → Promise
42 | Mutate elements of an array using a given callback. Return a value to replace the original item or a `Promise` object.
43 | ```javascript
44 | var array = [1, 2, 3, 4, 5];
45 |
46 | // Sync
47 | var promise = PromiseArrays.map(array, function (item, index) {
48 | return item * 10;
49 | }).then(function (result) {
50 | console.log(result); // [10, 20, 30, 40, 50]
51 | });
52 |
53 | // Async
54 | var promise = PromiseArrays.map(array, function (item, index) {
55 | return new Promise(function (resolve, reject) {
56 | setTimeout(function () {
57 | resolve(item * 10);
58 | }, 100);
59 | });
60 | }).then(function (result) {
61 | console.log(result); // [10, 20, 30, 40, 50] After ~ 100ms
62 | });
63 | ```
64 |
65 | You can also use `each` instead of `map`, which is basically an alias to `map`.
66 |
67 | ### PromiseArrays.filter(array, callback) → Promise
68 | Filter an array based on given criteria. API usage is similar to `.map`
69 | ```javascript
70 | var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
71 | var promise = PromiseArrays.filter(array, function (item, index) {
72 | return item > 3 && item < 8; // OR return a Promise
73 | }).then(function (result) {
74 | console.log(result); // [4, 5, 6, 7]
75 | });
76 | ```
77 |
78 | ## Test
79 | ```bash
80 | $ npm test
81 | ```
82 |
83 | ## Changelog
84 |
85 | | Version | Date | Notes |
86 | |---------|------------|-------|
87 | | 0.1.0 | 2015-09-13 | `resolve` is no more passed to callbacks. Callbacks should return value or `Promise` |
88 | | 0.0.2 | 2015-09-10 | Added tests |
89 | | 0.0.1 | 2015-09-04 | Initial release |
90 |
91 | ## License
92 | This software is released under the [MIT License](http://sallar.mit-license.org/).
93 |
94 | Copyright © 2015 Sallar Kaboli
95 |
96 | Permission is hereby granted, free of charge, to any person obtaining a copy
97 | of this software and associated documentation files (the “Software”), to deal
98 | in the Software without restriction, including without limitation the rights
99 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
100 | copies of the Software, and to permit persons to whom the Software is
101 | furnished to do so, subject to the following conditions:
102 |
103 | The above copyright notice and this permission notice shall be included in
104 | all copies or substantial portions of the Software.
105 |
106 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
107 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
108 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
109 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
110 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
111 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
112 | THE SOFTWARE.
113 |
114 | [npm-url]: https://npmjs.com/package/promise-arrays
115 | [npm-version-image]: https://img.shields.io/npm/v/promise-arrays.svg
116 |
117 | [travis-url]: https://travis-ci.org/sallar/promise-arrays
118 | [travis-build-image]: https://img.shields.io/travis/sallar/promise-arrays.svg
119 |
120 | [license-url]: http://sallar.mit-license.org/
121 | [license-image]: https://img.shields.io/npm/l/promise-arrays.svg
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Sallar Kaboli
3 | * @date 07.09.2015
4 | * @license
5 | * The MIT License (C) 2015 Sallar Kaboli
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining
8 | * a copy of this software and associated documentation files (the
9 | * "Software"), to deal in the Software without restriction, including
10 | * without limitation the rights to use, copy, modify, merge, publish,
11 | * distribute, sublicense, and/or sell copies of the Software, and to
12 | * permit persons to whom the Software is furnished to do so, subject to
13 | * the following conditions:
14 | *
15 | * The above copyright notice and this permission notice shall be
16 | * included in all copies or substantial portions of the Software.
17 | *
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 | */
26 | 'use strict';
27 |
28 | // UMD Definitions
29 | (function (name, definition) {
30 | // NodeJS & CommonJS
31 | if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
32 | module.exports = definition();
33 | }
34 | // AMD
35 | else if (typeof define === 'function' && typeof define.amd === 'object') {
36 | define(definition);
37 | }
38 | // Browser Globals
39 | else {
40 | this[name] = definition();
41 | }
42 | })('PromiseArrays', function () {
43 | /**
44 | * Async Array Map
45 | * performs async operations on arrays and returns a promise with the results
46 | * @TODO Handle Rejection
47 | * @param array {Array} Array to perform mapping on
48 | * @param callback {function} Function to apply to each item
49 | * @returns {Promise} Promise containing the results
50 | */
51 | function map (array, callback) {
52 | // Map each item to a new Promise
53 | array = array.map(function (item, index) {
54 | return new Promise(function (resolve) {
55 | // Pass callback to given callback
56 | resolve(callback(item, index));
57 | });
58 | });
59 |
60 | // Wait for all promises to complete
61 | return Promise.all(array);
62 | }
63 |
64 | /**
65 | * Async Array Filter
66 | * Filters an array based on async operations and returns promise with the results
67 | * @param array {Array} Array to perform filtering on
68 | * @param callback {function} Function to use as criteria
69 | * @returns {Promise} Promise containing filtered results
70 | */
71 | function filter (array, callback) {
72 | // Use async map function
73 | return map(array, callback).then(function (result) {
74 | // Then filter out false results
75 | return array.filter(function (item, index) {
76 | return result[index];
77 | });
78 | });
79 | }
80 |
81 | /* Public Interface */
82 | return {
83 | map : map, // Map
84 | each : map, // Each, alias to Map
85 | filter : filter // Filter
86 | };
87 | });
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "promise-arrays",
3 | "version": "0.1.0",
4 | "repository": "https://github.com/sallar/promise-arrays",
5 | "scripts": {
6 | "test": "./node_modules/mocha/bin/mocha"
7 | },
8 | "author": {
9 | "name": "Sallar Kaboli",
10 | "url": "http://sallar.me",
11 | "email": "sallar.kaboli@gmail.com"
12 | },
13 | "license": {
14 | "type": "MIT",
15 | "url": "http://sallar.mit-license.org/"
16 | },
17 | "devDependencies": {
18 | "chai-as-promised": "^5.1.0",
19 | "chai-things": "^0.2.0",
20 | "mocha": "^2.3.2",
21 | "chai": "^3.2.0"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/test/arrays.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Sallar Kaboli
3 | * @date 08.09.2015
4 | */
5 | "use strict";
6 |
7 | var chai = require('chai');
8 | chai.use(require('chai-things'));
9 | chai.use(require('chai-as-promised'));
10 | chai.should();
11 |
12 | var map = require(__dirname + '/..').map,
13 | filter = require(__dirname + '/..').filter;
14 |
15 | describe('Array Map', function() {
16 | it('maps an array correctly', function(done) {
17 | var arr = [1, 2, 3, 4];
18 |
19 | var arrMap = map(arr, function(item) {
20 | return item * 10;
21 | });
22 |
23 | Promise.all([
24 | arrMap.should.eventually.have.length(arr.length),
25 | arrMap.should.eventually.all.be.above(9)
26 | ]).should.notify(done);
27 | });
28 |
29 | it('maps an array async correctly', function(done) {
30 | var arr = [1, 2, 3, 4];
31 |
32 | var arrMap = map(arr, function(item) {
33 | return new Promise(function(resolve) {
34 | setTimeout(function() {
35 | resolve(item * 10);
36 | }, 100);
37 | });
38 | });
39 |
40 | Promise.all([
41 | arrMap.should.eventually.have.length(arr.length),
42 | arrMap.should.eventually.all.be.above(9)
43 | ]).should.notify(done);
44 | });
45 | });
46 |
47 | describe('Array Filter', function() {
48 | it('filters an array correctly', function(done) {
49 | var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
50 |
51 | var arrFilter = filter(arr, function(item, i, resolve) {
52 | return item > 3 && item < 8;
53 | });
54 |
55 | Promise.all([
56 | arrFilter.should.eventually.have.length(4)
57 | ]).should.notify(done);
58 | });
59 | });
--------------------------------------------------------------------------------
/test/mocha.opts:
--------------------------------------------------------------------------------
1 | --reporter spec
--------------------------------------------------------------------------------