Question

I am getting an error that I do not understand. I am calling async.waterfall with an array of functions. The function is 'shortened' for clarity.

FabricCommand.prototype.do = function (callback, undoArray) {
    var self = this;

    if (undoArray === undefined) {
        undoArray = [];
    }

    undoArray.push(self);
    callback(null, undoArray);
};

I create the array as listed below: doCommands is an array and the objects are added as such:

doCommands.push(fabricCommand.do.bind(fabricCommand));

the waterfall setup:

async.waterfall(
    doCommands,
    function(err, undoCommands){
        if (err) {
           // do something ...
        }
        else {
            console.log('we succeeded with all the do commands... and there are '
                + undoCommands.length
                + ' in the undoCommands but we will disregard it...');
        }
    }
);

Now when I run this code, the first time through the FabricCommand.do function, I allocate the undoCommands array and I add one to it, next time through I get, where I try to add the array element, the following error:

undoArray.push(something);
          ^ TypeError: Object function (err) {
            if (err) {
                callback.apply(null, arguments);
                callback = function () {};
            }
            else {
                var args = Array.prototype.slice.call(arguments, 1);
                var next = iterator.next();
                if (next) {
                    args.push(wrapIterator(next));
                }
                else {
                    args.push(callback);
                }
                async.setImmediate(function () {
                    iterator.apply(null, args);
                });
            }
        } has no method 'push'

Can anyone see what I am doing wrong?

Was it helpful?

Solution

The function that is executed by async.waterfall must have the following signature:

function(arg, callback) { … }

or, with multiple arguments:

function(arg1, arg2, callback) { … }

In your case, you simply inverted the two parameters:

 FabricCommand.prototype.do = function (callback, undoArray) { … }

callback received the value intended to be stored in undoArray, and undoArray received the value intended for the callback, i.e. a function: that's why you encountered this weird error (function […] has no method 'push').

You need to put the parameters in the correct order:

 FabricCommand.prototype.do = function (undoArray, callback) { … }

A second issue is that the first function of the waterfall receives only one parameter: the callback (because there is no value to be received, as it is the first function of the waterfall). A solution is to check the number of arguments:

if (Array.prototype.slice.apply(arguments).length === 1) {
    callback = undoArray;
    undoArray = undefined;
}

Here is a working gist.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top