Метод распространения обещаний Bluebird возвращает TypeError

Я не знаю, правильно ли я использую метод .spread при работе с промисами Bluebird в моделях Sails.js. Вот что у меня есть:

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);
    ...
})
...

После возврата [results, token] на втором .then (внутри обратного вызова криптографии) он выплевывает

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

Я удалил остальную часть кода после .spread, так как он не очень актуален, и именно здесь выполнение останавливается перед возвратом ошибки.

Я просто хочу передать переменные results и token в функцию внутри .spread. Что я делаю не так?

Любая помощь прекрасна. Спасибо.


person Lester    schedule 02.04.2015    source источник
comment
Вы уверены, что ваше выполнение останавливается на .spread()?   -  person Satyam Koyani    schedule 03.04.2015
comment
Да, ну, он не может выполнить код внутри .spread(), и я уверен, что все, что находится внутри криптографии, действительно запускается до возврата. Я предполагаю, что, может быть, мне не следует размещать асинхронный код, такой как crypto.randomBytes, внутри обещания? Или, возможно, просто сделайте crypto.randomBytes частью цепочки обещаний.   -  person Lester    schedule 03.04.2015
comment
Просто поместите console.log() и отследите, где останавливается ваше выполнение? Здесь ваша ошибка указывает на то, что любая из функций then() или spread() не получает ожидаемых аргументов, поэтому может быть, что ваш поток возвращается как неопределенный.   -  person Satyam Koyani    schedule 03.04.2015
comment
Это то, что я сделал. Размещение console.log("bla") перед return [results, token] приводит к регистрации bla. Но после этого ничего не пишет.   -  person Lester    schedule 03.04.2015


Ответы (2)


После возвращения [results, token] на второй .then

Это не то, что вы делаете. Вы возвращаетесь внутрь обратного вызова криптографии, где это бессмысленно. Никто не знает об этом обратном вызове, и вы на самом деле ничего не знаете из then обратного вызова.

первое правило разработки промисов: обещать базовый API, чтобы вы могли работать с чистыми обещаниями.

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

Теперь мы можем следовать правилу 3b и фактически вернуть (обещание) результат обратного вызова then:

…
.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);
    …
})
person Bergi    schedule 03.04.2015

.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];
    });
})

неправильно. Вы return int внутри обратного вызова randomBytes, а не внутри then, поэтому ваш then просто возвращает undefined, а затем вы пытаетесь .spread сделать это. Чтобы правильно дождаться randomBytes, вам нужно создать обещание для этого значения.

.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]);
        });
    });
})
person loganfsmyth    schedule 03.04.2015