Использование сопрограммы Bluebird

Я пытаюсь использовать сопрограммы Bluebird следующим образом:

var p = require('bluebird');
//this should return a promise resolved to value 'v'
var d = p.coroutine(function*(v) { yield p.resolve(v); });
//however this prints 'undefined'
d(1).then(function(v){ console.log(v); });

Что здесь неправильно?

Ответы

Ответ 1

Цитирование документации coroutine,

Возвращает функцию, которая может использовать yield для получения promises. Контроль возвращается обратно генератору, когда достигнуто обещание.

Таким образом, функция может использовать yield, но yield не используется для возврата значения из функции. Независимо от того, что вы возвращаете из этой функции с помощью оператора return, будет фактическое разрешенное значение функции сопрограммы.

Promise.coroutine просто заставляет оператор yield ожидать, что обетование будет разрешено, и фактическое выражение yield будет оцениваться по разрешенному значению.

В вашем случае выражение

yield p.resolve(v);

будет оцениваться до 1, и поскольку вы ничего не возвращаете из функции, по умолчанию JavaScript возвращает undefined. Вот почему вы получаете undefined в качестве результата.


Чтобы исправить это, вы можете фактически вернуть полученное значение, например

var p = require('bluebird');

var d = p.coroutine(function* (v) {
    return yield p.resolve(v);
});

d(1).then(console.log);

Ответ 2

Начнем с вашего кода:)

var d = p.coroutine(function*(v) { 
    yield p.resolve(v); 
});

Когда вы делаете d (1), синтагеля bluebird делает это волшебство и оценивает функцию обещания i.e p.resolve(v). Теперь, как работает coroutine, вызывается функция обещания, а затем выполняется фактический выход, и поток возвращается к фактическому генератору после выполнения обещанного обещания.

Теперь доход не для возвращаемых значений, в отличие от функции разрешения, которая может использоваться для получения значений в "then" в случае promises.

Таким образом, никакое значение не возвращается и, следовательно, вы получаете undefined.

Итак, вы можете сделать две вещи:

Сначала просто возвращаем значение yield явно:

var d = p.coroutine(function* (v) {
    return p.resolve(v);
})

это вернет значение, полученное в "доходности", полученное выполнением обещания, поэтому значение можно получить, используя "then". как

d(7).then((val) => {
    console.log(val);
});

но что, если у вас есть другая функция обещания. что-то вроде этого:

var d = bluebird.coroutine(function* (val) {
    yield bluebird.resolve(val);
    console.log('i am here');
    yield(bluebird.resolve('here' + val));
    console.log('i am at the last');
});

тогда выполнение функции возврата здесь не будет выполнять другую функцию yield. Если вы вернетесь с первым значением доходности в приведенном выше коде, тогда код после первого выхода не будет выполнен.

Итак, есть одна вещь, которую я могу сделать - это обработать "то" данного обещания там, как:

var d = bluebird.coroutine(function* (val) {
    yield bluebird.resolve(val).then(function(data) {
        // process data here
        console.log(data);
    });
});

d(4).then(() => {
    console.log('done execution');
});

и это вы можете сделать с любым отсутствием promises. Вот демонстрационный код:

var bluebird = require('bluebird');
bluebird.coroutine(function *temp() {
    console.log('starting');
    yield(new Promise((resolve, reject) => { 
            setTimeout(function() {
                    return resolve('first yield data');
            }, 2000);
    }).then((data)=>{console.log(data)}));

    yield(new Promise((resolve, reject) => {
            setTimeout(function() {
                    resolve('second yield data');
            }, 3000);
    }).then((data) => {console.log(data)}));
})().then(() => {
         console.log('finally done');
     });

Таким образом вы можете получить как можно больше promises в bluebird и получить значения, разрешенные ими в соответствующем "затем", и обработать разрешенные данные.