Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bluebird promise spread method returns TypeError

I don't know if I'm not using the .spread method correctly while working with Bluebird promises on Sails.js models. Here's what I have:

transactionAsync('BEGIN')
.then(function() {
    return Model.findOne({ id: 5) });
})
.then(function(results){
    if(!results) {
        return res.notFound();
    }
    crypto.randomBytes(24, function(err, buf) {
        if(err) throw new Error(err);
        var token =  buf.toString('hex');
        // This is where it fails
        return [results, token];
    });
})
.spread(function(results, token) {
    // It doesn't get to log these
    console.log(results, token);
    ...
})
...

After returning [results, token] on the second .then (inside of the crypto callback), it spits out

[TypeError: expecting an array, a promise or a thenable]

I removed the rest of the code after .spread, since it's not really relevant, and that's where execution stops before returning an error.

I just want to pass variables results and token to the function inside of .spread. What am I doing wrong?

Any help is great. Thanks.

like image 571
Lester Avatar asked Feb 06 '26 19:02

Lester


2 Answers

After returning [results, token] on the second .then

That's not what you're doing. You're returning inside of the crypto callback, where it is meaningless. Neither does anybody know of this callback, nor do you actually return anything from the then callback.

The first rule of promise development is to promisify the underlying API so that you can work on pure promises.

var crypto = Promise.promisifyAll(crypto);
// or specifically:
var randomBytes = Promise.promisify(crypto.randomBytes);

Now we can follow rule 3b and actually return a (promise) result from then then callback:

…
.then(function(results) {
    if (!results) {
        return res.notFound();
    }
    return crypto.randomBytesAsync(24) // returns a promise now!
//  ^^^^^^
    .then(function(buf) {
        var token = buf.toString('hex');
        return [results, token];
    });
})
.spread(function(results, token) {
    console.log(results, token);
    …
})
like image 73
Bergi Avatar answered Feb 08 '26 14:02

Bergi


.then(function(results){
    if(!results) {
        return res.notFound();
    }
    crypto.randomBytes(24, function(err, buf) {
        if(err) throw new Error(err);
        var token =  buf.toString('hex');
        // This is where it fails
        return [results, token];
    });
})

is wrong. You are return int from inside the randomBytes callback, not inside the then, so your then simply returns undefined and you then try to .spread that. In order to properly wait for randomBytes, you need to create a promise for that value.

.then(function(results){
    if(!results) {
        return res.notFound();
    }

    return new Promise(function(resolve, reject){
        crypto.randomBytes(24, function(err, buf) {
            if(err) return reject(new Error(err));
            var token =  buf.toString('hex');
            // This is where it fails
            resolve([results, token]);
        });
    });
})
like image 45
loganfsmyth Avatar answered Feb 08 '26 13:02

loganfsmyth



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!