0

如何使用 co() 包装函数与普通同步代码集成?

例如,我已经co.wrapped 这个函数使用 yield 在 mongo 上调用异步方法:

let wrap = co.wrap(function* (collName) {
  debug("collName", collName);
  let collection = AppConfig.db.collection(collName);
  let res = yield collection.findOne({});
  debug("res", res);
  yield res;
});

这是用这个调用的:

//
class TopicsResponse {

  public static topics(bot, message) {
    let topic = wrap("Topics");
    debug("topic", topic);
    topic.then( function() {
      debug("topic.then", topic);
      bot.reply(message, "topics:" + topic.cname);
    });
  }
//
}

它给出了如下的日志:

TopicsResponse collName +3s Topics TopicsResponse topic +2ms Promise { <pending> } TopicsResponse res +1ms { _id: 56d6bdd93cf89d4082e1bd27, cname: 'nodejs', username: 'bob' } TopicsResponse topic.then +1ms Promise { undefined }

所以在co.wrapped方法内部, res 有真实的数据:{ cname: nodejs }等等。但它返回/返回的内容是未定义的。

我认为这与生成器函数产生一个承诺有关..

我也试过了

yield collection.findOne({});

返回

Promise { undefined }

是否有可能以这种方式使用 co 来使异步代码看起来/运行像同步代码?我见过的其他示例只是将所有内容都放在顶层 co() 中,例如http://mongodb.github.io/node-mongodb-native/2.1/api/Collection.html#find

更新,这使用承诺:

let getTopic = co.wrap(function* (collName) {
  debug("collName", collName);
  let collection = AppConfig.db.collection(collName);
  let res = yield collection.findOne({});
  debug("res", res);  // prints correctly
  return res;
  // yield res;
});



//
class TopicsResponse {

  public static topics(bot, message) {
    let topic = getTopic("Topics");
    debug("topic", topic);
    topic.then( function(doc) {
      debug("doc", doc);
      debug("topic.then", topic);
      bot.reply(message, "topics:" + doc.cname);
    });
  }
//
}

但我想将所有丑陋的承诺包装.then()代码推入库中,而不必将它撒在我的应用程序中......

4

1 回答 1

0

不,一旦你用承诺“弄脏”了你的代码,它就必须一直是承诺(这与回调相同)。

你必须用一个电话来包装一切。co(当异步函数落地时,这也会以这种方式运行。

这不是“人工制品”或设计问题——它实际上非常有用,因为它可以向您展示代码的哪些部分是异步的,哪些不是。

如果您将所有内容都包含在co您的代码中,那么您将拥有明确的代码 - 但不是丑陋的代码。您确切地知道哪些方法可以执行 I/O,哪些方法不执行 I/O。

于 2016-03-03T19:42:13.410 回答