-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add someLimit and everyLimit #828
Conversation
When checking if a folder contains subfolders or not (fs.readdir -> fs.stat -> some(is_a_Folder)), getting crashes when listing Windows shares from Ubuntu VM. someLimit avoids the problem. Test for someLimit added anyLimit alias and updated doc. removed anyLimit alias
gyeates at boompad in ~/code/async on arr-testers [!$]
$ ./perf/benchmark.js -g some
Comparing 1.2.1 with current on Node v0.12.0
--------------------------------------
some - no short circuit- false(500) 1.2.1 x 1,838 ops/sec ±5.41% (23 runs sampled), 0.544ms per run
some - no short circuit- false(500) current x 1,899 ops/sec ±4.72% (25 runs sampled), 0.527ms per run
Tie
--------------------------------------
some - short circuit - true(500) 1.2.1 x 1,598 ops/sec ±10.93% (25 runs sampled), 0.626ms per run
some - short circuit - true(500) current x 2,007 ops/sec ±5.35% (26 runs sampled), 0.498ms per run
current is faster
--------------------------------------
current faster overall (1.02ms total vs. 1.17ms total)
current won more benchmarks (1 vs. 0)
gyeates at boompad in ~/code/async on arr-testers [!$]
$ ./perf/benchmark.js -g every
Comparing 1.2.1 with current on Node v0.12.0
--------------------------------------
every - no short circuit- true(500) 1.2.1 x 1,388 ops/sec ±14.84% (18 runs sampled), 0.72ms per run
every - no short circuit- true(500) current x 1,634 ops/sec ±6.52% (21 runs sampled), 0.612ms per run
current is faster
--------------------------------------
every - short circuit - false(500) 1.2.1 x 1,828 ops/sec ±5.13% (26 runs sampled), 0.547ms per run
every - short circuit - false(500) current x 1,682 ops/sec ±6.95% (24 runs sampled), 0.595ms per run
Tie
--------------------------------------
current faster overall (1.21ms total vs. 1.27ms total)
current won more benchmarks (1 vs. 0) |
I've thought a lot about the best way to short circuit in the more general case. I've thought about defining a constant like function done(err) {
if (err) {
return callback(err === async.BREAK ? null : err);
}
//..
} Seems a bit hackish, but I haven't thought of something better. This type of strategy would also help in things like |
But 👍 for this otherwise, just waiting for CI. |
function _createTester(eachfn, check, defaultValue) { | ||
return function(arr, limit, iterator, cb) { | ||
function done() { | ||
if (cb) cb(defaultValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add cb = cb || noop
to prevent having to check for this every time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is only done at the last step, noop
actually makes it more complicated because then at the other step (iterator) it has to check if (cb === noop)
Yeah, thats what underscore used to do and makes sense if false doesn't work |
Do you know why underscore moved away from it? |
@aearly should I add a unit test to ensure some and every short circuit? |
Yes -- always best to have tests for all the corner cases wherever possible. |
Yeah, for performance reasons we implemented it as a |
|
Ahh, I see --- it wasn't like lodash where it has a generic way to break, it was a special behavior for |
Why don't we save the short circuiting for 2.0 -- you're right -- it will have minor breaking changes. |
IDK, I think the current behaviour can also be classified as a bug as people usually expect |
This can also be used to implement |
Actually, I realize short circuiting isn't breaking at all. Since we're using the parallel |
Nope, |
They exit early, but the iterators are still called for every element in the array. The callbacks are just ignored once the relevant |
Unless we're talking about a different subtle breaking change. |
For synchronous iterators, |
Well, this test didn't break, so I think we're okay. |
It'll break if you remove the setTimeout :) |
* [`someLimit`](#someLimit) | ||
* [`every`](#every) | ||
* [`concat`](#concat) | ||
* [`concatSeries`](#concatSeries) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In #809, I updated how the docs are formatted where the series and limit functions no longer need their own documentation. Instead the series/limit is documented as whole and then the related commands are just mentioned with the documentation of the normal command.
These lines should become
* [`some`](#some), `someLimit`
* [`every`](#every), `everyLimit`
* [`concat`](#concat), `concatSeries`
And the documentation for someLimit should be removed and the following should be added to the some
documentation.
__Related__
* someLimit(arr, limit, iterator, [callback])
Same for every.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @charlierudolph, if you have some time would you mind submitting a pull request with your suggested documentation changes?
Merges the implementations of
some
andevery
and adds their respective limit functions (with partial short circuiting)PS I think short circuiting should be done like lodash does it (allowing
each
to break):if
cb
resolves withcb(false)
you break the loop (in lodash if you return false it breaks the loop)Resolves #548