【问题标题】:Bluebird coroutine usage蓝鸟协程使用
【发布时间】:2015-09-06 18:31:44
【问题描述】:

我正在尝试如下使用 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); });

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

【问题讨论】:

    标签: javascript node.js promise bluebird coroutine


    【解决方案1】:

    引用documentation of coroutine

    返回一个可以使用yield 来产生承诺的函数。当 yield 的 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);
    

    【讨论】:

    • 所以,我也可以p.coroutine(function*() { yield d(1); }) 对吗?
    • @pkyeck 在你的情况下d 是什么?
    • 您在示例中创建的协程
    【解决方案2】:

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

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

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

    现在 yield 不是用于返回值,这与 resolve 函数不同,在 promise 的情况下可以用来获取 'then' 中的值。

    所以没有返回值,因此你得到未定义。

    所以你可以做两件事:

    首先简单地显式返回产量值:

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

    this 会返回执行 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');
    });
    

    然后这里做return的事情不会执行另一个yield函数,即如果你在上面代码中的第一个yield值处返回,那么第一个yield之后的代码将不会执行。

    所以我可以做的一件事就是在那里处理给定承诺的“then”,如下所示:

    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 中产生尽可能多的 Promise,并在它们各自的“then”中获取由它们解析的值并处理解析的数据。

    【讨论】:

      【解决方案3】:
      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}
      

      【讨论】:

      • 只有代码的答案通常没有用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多