1

I'm using the when promise library to lift() my node style callbacks and promisify them...

var nodefn = require('when/node');

var one = nodefn.lift(oneFn),
    two = nodefn.lift(twoFn),
    three = nodefn.lift(threeFn);


function oneFn(callback){
    console.log('one');
    callback(null);
}

function twoFn(callback){
    console.log('two');
    callback(null);
}

function threeFn(callback){
    console.log('three');
    callback(null);
}

I want to call the functions in a chain, like this:

one().then(two).then(three).done();

But it gives me an error when calling the second callback function:

Uncaught TypeError: undefined is not a function

The error refers to the callback function within twoFn(callback).

What is the correct way to chain these functions together and execute one after the other?

Drahcir
  • 11,772
  • 24
  • 86
  • 128
  • 1
    I haven't used `when` for a while and don't know `when.lift`, but I guess you would need to do: `one().then(function() { return two();}).then(function() {return three();}).done();` – t.niese Feb 20 '15 at 12:16

2 Answers2

2

The problem is that nodefn.lift doesn't know how many parameters the function has (zero), so it just takes the appearing arguments and appends its callback to them. In a then chain every callback receives the result of the previous promise (in your case: undefined), so your twofn will be called with two arguments: undefined and the nodeback.

So if you fix their arities, it should work:

Function.prototype.ofArity = function(n) {
    var fn = this, slice = Array.prototype.slice;
    return function() {
        return fn.apply(null, slice.call(arguments, 0, n));
    };
};
var one = nodefn.lift(oneFn).ofArity(0),
    two = nodefn.lift(twoFn).ofArity(0),
    three = nodefn.lift(threeFn).ofArity(0);
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

Based on @Bergi's answer, I wrote this function:

function nodeLift(fn){
    return function(){
        var args = Array.prototype.slice.call(arguments, 0, fn.length - 1),
            lifted = nodefn.lift(fn);

        return lifted.apply(null, args);
    };
}
Drahcir
  • 11,772
  • 24
  • 86
  • 128
  • I think you should use `nodefn.apply` directly, or otherwise put `var lifted = …` above the `return function(){` – Bergi Feb 20 '15 at 12:40
  • Also note that this function is clever, but it's *too* clever for functions that have optional parameters. Proceed with care :-) – Bergi Feb 20 '15 at 12:43