Skip to content

Commit

Permalink
Add find and findSeries
Browse files Browse the repository at this point in the history
  • Loading branch information
mwilliamson committed Apr 14, 2013
1 parent c5a1294 commit c2f5535
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 3 deletions.
21 changes: 21 additions & 0 deletions README.md
Expand Up @@ -121,3 +121,24 @@ Arguments:
The same as `filter`,
except that `iterator` is only called on each element once the previous
application of `iterator` has finished.

### find(array, iterator)

Find an element in `array` that satisfies `iterator`.
`find` runs in parallel, and will return the first matching value to return,
which may not be the first matching value in the array.

Arguments:

* `array` -- an array to iterate over.
* `iterator(element, index)` -- the iterator is passed each element of the array
and its index. Should return a promise of a boolean.

### findSeries(array, iterator)

The same as `find`,
except that `iterator` is only called on each element once the previous
application of `iterator` has finished.
This means that the value returned is the first matching value in the array.


28 changes: 25 additions & 3 deletions lib/index.js
Expand Up @@ -85,8 +85,8 @@ function createUtilities(createPromise) {
function forEachSeries(array, iterator) {
var index = 0;

function next() {
if (index < array.length) {
function next(value) {
if (index < array.length && value !== stopValue) {
var result = iterator(array[index], index);
index++;
return result.then(next);
Expand Down Expand Up @@ -157,6 +157,23 @@ function createUtilities(createPromise) {
};
}

function createFindFunc(forEachFunc) {
return function(array, iterator) {
var result = notFound;
return forEachFunc(array, function(element, index) {
return iterator(element, index)
.then(function(isMatch) {
if (isMatch && result === notFound) {
result = element;
return stopValue;
}
});
}).then(function() {
return result;
});
};
}

return {
create: createPromise,
resolved: resolved,
Expand All @@ -166,6 +183,11 @@ function createUtilities(createPromise) {
mapSeries: createMapFunc(forEachSeries),
map: createMapFunc(forEach),
filterSeries: createFilterFunc(forEachSeries),
filter: createFilterFunc(forEach)
filter: createFilterFunc(forEach),
findSeries: createFindFunc(forEachSeries),
find: createFindFunc(forEach)
};
}

var stopValue = {};
var notFound = {};
40 changes: 40 additions & 0 deletions tests/patter.tests.js
Expand Up @@ -279,6 +279,46 @@ test("filter returns promise of filtered array", function(promises, test) {
});
});

// findSeries

test("findSeries returns promise of first matching element", function(promises, test) {
function iterator(element, index) {
return promises.create(function(resolve, reject) {
setTimeout(function() {
resolve(index % 2 === 1)
}, (4 - index) * 10);
});
}

test.expect(1);
return promises.findSeries(["apple", "banana", "coconut", "durian"], iterator)
.then(function(value) {
test.deepEqual(value, "banana");
test.done();
});
});

// find

test("find returns promise of first-to-return matching element", function(promises, test) {
function iterator(element, index) {
return promises.create(function(resolve, reject) {
setTimeout(function() {
resolve(index % 2 === 1)
}, (4 - index) * 10);
});
}

test.expect(1);
return promises.find(["apple", "banana", "coconut", "durian"], iterator)
.then(function(value) {
test.deepEqual(value, "durian");
test.done();
});
});



function test(name, func) {
var impls = ["promise", "q", "when", "deferred"];

Expand Down

0 comments on commit c2f5535

Please sign in to comment.