-
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
"Reflect" behavior for collecting errors/results and continuing. #942
Comments
I would suggest |
Any update of this? |
Sorry, we've been too busy to make any progress on this. We also haven't decided on the naming pattern, and haven't thought up a clean way to add it to the library. |
Actually bluebird is switching to a map with a reflect wrapper around each. Maybe that would be easier? So reflect would wrap each of the callbacks and always return successful. The output would then have null as error and a list of reflect objects that with have a function Here is what the code would look like. async.series([
async.reflect(function(callback){
// do some stuff ...
callback(null, 'one');
}),
async.reflect(function(callback){
// do some more stuff but error ...
callback(new Error('bad stuff happened'));
}),
async.reflect(function(callback){
// do some more stuff ...
callback(null, 'two');
})
],
// optional callback
function(err, results){
// values
// results[0].value = 'one'
// results[1].error = Error('bad stuff happened')
// results[2].value = 'two'
}); |
We can add a reflectAll function as well that can take a list of functions with callbacks and wrap them all in async.reflect like this: let tasks = [
function(callback){
setTimeout(function(){
callback(null, 'one');
}, 200);
},
function(callback){
// do some more stuff but error ...
callback(new Error('bad stuff happened'));
}
function(callback){
setTimeout(function(){
callback(null, 'two');
}, 100);
}
];
async.parallel(async.reflectAll(tasks),
// optional callback
function(err, results){
// values
// results[0].value = 'one'
// results[1].error = Error('bad stuff happened')
// results[2].value = 'two'
}); |
@jtwebman I like your approach. It means we don't have to create new methods for each flavor of async function, leaving it to the user to use it when continuing is desired. Also, +1 for the consistency with Bluebird's direction. |
Great idea, although the only thing that irks me is wrapping the tasks themselves. Say something like :
|
@danielshir How is that different then this: let tasks = [
function(callback){
setTimeout(function(){
callback(null, 'one');
}, 200);
},
function(callback){
// do some more stuff but error ...
callback(new Error('bad stuff happened'));
}
function(callback){
setTimeout(function(){
callback(null, 'two');
}, 100);
}
];
async.parallel(async.reflectAll(tasks),
// optional callback
function(err, results){
// values
// results[0].value = 'one'
// results[1].error = Error('bad stuff happened')
// results[2].value = 'two'
}); This way is more explicit without having to hide some magic under some object that treats parallel or any other method different plus not all methods make sense to use reflect. |
…a object with error or value property set. This is one way to solve issue caolan#942.
Well, if that's your writing style then I guess it looks the same. It's a bit messy for my taste since you're adding another scope (more parentheses) - async.parallel(async.reflectAll([function(callback){
setTimeout(function(){
callback(null, 'one');
}, 200);
},
function(callback){
// do some more stuff but error ...
callback(new Error('bad stuff happened'));
}
function(callback){
setTimeout(function(){
callback(null, 'two');
}, 100);
}]
),
// optional callback
function(err, results){
// values
// results[0].value = 'one'
// results[1].error = Error('bad stuff happened')
// results[2].value = 'two'
}); |
@danielshir Then you can write it like this if you want: async.parallel([function(callback){
setTimeout(function(){
callback(null, 'one');
}, 200);
},
function(callback){
// do some more stuff but error ...
callback(new Error('bad stuff happened'));
}
function(callback){
setTimeout(function(){
callback(null, 'two');
}, 100);
}].map(async.reflect),
// optional callback
function(err, results){
// values
// results[0].value = 'one'
// results[1].error = Error('bad stuff happened')
// results[2].value = 'two'
}); Leaving these just functions keeps it very simple and doesn't spread the code to do this all over the place. |
@jtwebman I didn't think of that and that actually looks way better! |
I'm very interested in this feature, thanks for your work guys. +1 |
+1 |
Great feature for me, but I do not see this in 2.0.0-rc.1 - Any hope it will be ready soon ? |
We're waiting for #1012 to be completed. No ETA. It might wait until 2.1. |
Closed via #1095 ! |
How to continue *parallel* processing in case of a failing task seems to be a frequently asked question. It was mentioned in several issues: - caolan/async#334 - caolan/async#675 - caolan/async#798 - caolan/async#942 Adding a hint to the documentation might help users of the library to find out about the answer to this question.
Related to #349 #334 #531 .
There have been many requests for a behavior where when an iterator calls back with an error, the error is collected, and execution continues. There have been a couple attempts at this feature, but the implementations fall short.
In theory, this would be applied to just about any async function,
map
,series
,parallel
,forEachSeries
, etc.. I'd like to support this broadly, but without having to create duplicate implementations for each function. Something we can wrap existing functions with, without having to modify the implementations.We also need to settle on what the name is for this type of behavior. These have been proposed:
mapCollect
/parallelCollect
/eachSeriesCollect
mapContinue
/parallelContinue
/eachSeriesContinue
mapAnyway
/parallelAnyway
/eachSeriesAnyway
mapMaybe
/parallelMaybe
/eachSeriesMaybe
mapResume
/parallelResume
/eachSeriesResume
Lastly -- how should the collected results be passed to the final callback?
callback(null, {errors: [], results: []])
callback(null, [Error, results, results, Error, results..])
callback(null, [{err: null, result: results0}, {err: Error, result: null}, ...])
callback(null, results, errors)
The text was updated successfully, but these errors were encountered: