Использование сопрограммы 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 и получить значения, разрешенные ими в соответствующем "затем", и обработать разрешенные данные.