-
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
Fix for Stack Overflow in Whilst and Until #133
Conversation
Your iterator is not asynchronous, that is why you're getting a stack overflow. This function is designed for asynchronous operations, while adding nextTick would stop it breaking on synchronous iterators, it's a good indicator that you're using the wrong tool and you should probably be using a normal while loop. |
Let's say our iterator does something like this: var i, user_ids = [1,2,3]; // ...
iterator = function(cb) {
// Get from cache, sync function
user = cache.get_user(user_ids[i]);
if (user) {
i++;
cb();
} else {
// Get from the DB, async
mongo.get_user(user_ids[i++], cb);
}
} This might break. I think async should support this behavior of sometimes doing a sync and sometimes async work. |
@Radagaisus 's code is reallistic and would break in some cases (many users, all cached). I made a pull request (#135) which make whilst/until support sync and async cases. |
I agree this is an issue worth fixing -- i just hit the same issue in my code (cached path is synchronous, non-cached path is asynchronous). That said, this issue affects more than just whilst/until in the async library -- other control flow options like forEachLimit are also affected as far as i can tell. So would be ideal to have a async-wide fix here. For now, i'm working around it manually by calling nextTick() on the otherwise synchronous paths... |
@caolan said "while adding nextTick would stop it breaking on synchronous iterators, it's a good indicator that you're using the wrong tool and you should probably be using a normal while loop" Any tools you can suggest? Having to fallback to while loops, setTimeout calls, and duty calculations is a pain in the ass. Definitely not something you want to have to think about every time you need to work with a long running client-side operation. |
You may want to check out Node.js's own documentation on nextTick which highly suggests you don't write functions that are sometimes sync and other times async, as it can cause unexpected behavior when the caller expects the function to be async (like this module). |
@dougwilson from the docs: function definitelyAsync(arg, cb) {
if (arg) {
process.nextTick(cb);
return;
}
fs.stat('file', cb);
} Which is exactly the same as this pull request, we use |
No, the |
+1 |
This kind of thing comes up fairly often so it's clearly confusing for some people. However, I consider this to be a useful indicator that your function is not following Node.js convention. If a function is asynchronous, it should always be asynchronous. |
As long it's made clear what |
This is a very common problem that inflicts with many other subjects as well: If |
Why restricting the user to only async functions, or even advise him to use plattform specific code ( The problem can be solved in the |
you don't have to use platform specific code as you can use this is a library for handling asynchrounos code, so why use it for synchrounos functions? :) |
@Radagaisus 's example with mixed sync/async code and there are many more usecases. :) |
Fixed in 6ad64ac |
Hey,
The solution is simple, I've just added
async.nextTick
, similar to this pull request.I've also taken the liberty to DRY up
whilst
anduntil
.until
now creates an anonymous function that negates the test it's given, then pass it along toasync.whilst
.