蓝鸟出游用法

Bluebird coroutine usage

本文关键字:用法 蓝鸟      更新时间:2023-09-26

我正试图使用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); });

这里有什么不正确的地方?

引用coroutine、的文档

返回一个可以使用yield生成promise的函数。当生成的promise结算时,控制权将返回给生成器。

因此,函数可以使用yield,但yield不用于从函数返回值。使用return语句从该函数返回的内容将是协程函数的实际解析值。

Promise.coroutine只是让yield语句等待promise解析,实际的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);

让我们从您的代码开始:)

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

当你做d(1)时,bluebird的协程会发挥它的魔力,并评估promise函数,即p.resolve(v)。现在,协程的工作方式是调用promise函数然后执行实际的yield,即流在执行产生的promise后返回到实际的生成器。

现在,yield不用于返回值,不像resolve函数,后者可以在promise的情况下用于获取"then"中的值。

因此,不会返回任何值,因此会得到未定义的值。

所以你可以做两件事:

首先简单地显式返回收益率值:

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

这将返回通过执行promise获得的yield中获得的值,因此可以使用then获得值。像

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

但是,如果您有另一个promise函数,该怎么办。例如:

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函数,即如果您在上面的代码中返回第一个yield值,那么第一个yide之后的代码将不会执行。

因此,我可以做的一件事是处理给定承诺本身的"当时":

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

而这一点你可以在任何不让步的承诺下做到。这是一个演示代码:

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

通过这种方式,您可以在bluebird中产生尽可能多的承诺,并在各自的"then"中获得由它们解析的值,并处理解析的数据。

function co(gen) {
    const it = gen(), next = it.next.bind(it), raise = it.throw.bind(it);
    return () => new Promise((resolve, reject) => {
        const factory = (fn) => (data) => {
            try {
                const {value, done} = fn(data);
                if (done) {
                    resolve(value);
                } else {
                    Promise.resolve(value).then(factory(next), factory(raise));
                }
            } catch(reason) {
                reject(reason);
            }
        };
        factory(next)();
    });
}
const example = co(function*() {
    // const x = yield Promise.reject(12);
    const x = yield Promise.resolve(12);
    return x
    // throw x
});
example(); // Promise {<resolved>: 12}