Repository: caolan/async (JavaScript)

Issue:
Feature request: reflect() should return values even when there is error
I have a function that will always return a "fallback" value to the callback, even if there's an error. I would really like reflect() / reflectAll() to capture this value.

For example:

```
function myFunc(callback){
    return callback('my error, 'my fallback value')
}

async.parallel(reflectAll({
   myval: myFunc
}), function(err, r){
    // r.myval.error = 'my error'
    // r.myval.value = 'my fallback value'
});
```



Discussion:
Good point, we could easily return both the error and value in that case.



Patch:
diff --git a/lib/reflect.js b/lib/reflect.js
index acd3043da..d2930a057 100644
--- a/lib/reflect.js
+++ b/lib/reflect.js
@@ -44,14 +44,18 @@ export default function reflect(fn) {
     var _fn = wrapAsync(fn);
     return initialParams(function reflectOn(args, reflectCallback) {
         args.push((error, ...cbArgs) => {
+            let retVal = {};
             if (error) {
-                return reflectCallback(null, { error });
+                retVal.error = error;
             }
-            var value = cbArgs;
-            if (cbArgs.length <= 1) {
-                [value] = cbArgs
+            if (cbArgs.length > 0){
+                var value = cbArgs;
+                if (cbArgs.length <= 1) {
+                    [value] = cbArgs;
+                }
+                retVal.value = value;
             }
-            reflectCallback(null, { value });
+            reflectCallback(null, retVal);
         });
 
         return _fn.apply(this, args);


Test patch:
diff --git a/test/es2017/asyncFunctions.js b/test/es2017/asyncFunctions.js
index 680725bb7..59c0df8fd 100644
--- a/test/es2017/asyncFunctions.js
+++ b/test/es2017/asyncFunctions.js
@@ -656,7 +656,10 @@ module.exports = function () {
             throw thrown;
         });
         fn(1, (err, result) => {
-            expect(result).to.eql({error: thrown});
+            expect(result).to.eql({
+                error: thrown,
+                value: undefined
+            });
             done(err);
         })
     });
diff --git a/test/parallel.js b/test/parallel.js
index ad1f44eab..e95e65cdc 100644
--- a/test/parallel.js
+++ b/test/parallel.js
@@ -269,14 +269,18 @@ describe('parallel', () => {
             }),
             async.reflect((callback) => {
                 callback(null, 2);
+            }),
+            async.reflect((callback) => {
+                callback('error3');
             })
         ],
         (err, results) => {
             assert(err === null, err + " passed instead of 'null'");
             expect(results).to.eql([
-                { error: 'error' },
-                { error: 'error2' },
-                { value: 2 }
+                { error: 'error', value: 1 },
+                { error: 'error2', value: 2 },
+                { value: 2 },
+                { error: 'error3' },
             ]);
             done();
         });
@@ -296,6 +300,11 @@ describe('parallel', () => {
                 setTimeout(() => {
                     callback(null, 'three');
                 }, 100);
+            },
+            four(callback) {
+                setTimeout(() => {
+                    callback('four', 4);
+                }, 100);
             }
         };
 
@@ -303,7 +312,8 @@ describe('parallel', () => {
             expect(results).to.eql({
                 one: { value: 'one' },
                 two: { error: 'two' },
-                three: { value: 'three' }
+                three: { value: 'three' },
+                four: { error: 'four', value: 4 }
             });
             done();
         })
@@ -321,21 +331,21 @@ describe('parallel', () => {
     it('parallel empty object with reflect all (errors)', (done) => {
         var tasks = {
             one(callback) {
-                callback('one');
+                callback('one', 1);
             },
             two(callback) {
                 callback('two');
             },
             three(callback) {
-                callback('three');
+                callback('three', 3);
             }
         };
 
         async.parallel(async.reflectAll(tasks), (err, results) => {
             expect(results).to.eql({
-                one: { error: 'one' },
+                one: { error: 'one', value: 1 },
                 two: { error: 'two' },
-                three: { error: 'three' }
+                three: { error: 'three', value: 3 }
             });
             done();
         })
diff --git a/test/series.js b/test/series.js
index 2b24c6f29..48e9379d4 100644
--- a/test/series.js
+++ b/test/series.js
@@ -118,14 +118,18 @@ describe('series', () => {
             }),
             async.reflect((callback) => {
                 callback(null, 1);
+            }),
+            async.reflect((callback) => {
+                callback('error3');
             })
         ],
         (err, results) => {
             assert(err === null, err + " passed instead of 'null'");
             expect(results).to.eql([
-                { error: 'error' },
-                { error: 'error2' },
-                { value: 1 }
+                { error: 'error', value: 1 },
+                { error: 'error2', value: 2 },
+                { value: 1 },
+                { error: 'error3' },
             ]);
             done();
         });