【问题标题】:using co and promises from sync code (mongoDB example)使用同步代码中的 co 和承诺(mongoDB 示例)
【发布时间】:2016-03-03 17:35:43
【问题描述】:

如何使用 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

更新,这使用 Promise 有效:

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() 代码的丑陋承诺推送到库中,而不必将其洒在我的应用程序中...

【问题讨论】:

  • 您的意思是生成器函数中的return res 吗?
  • 其实是的,return res 还给了promise,但它仍然是一个promise。我想没有办法得到结果(承诺解决方案?)
  • res 不是一个承诺 - findOne(…) 是一个。 topic 将是另一个承诺,doc 是结果值。除了将生成器代码包装在co 中或明确使用then 之外,没有其他方法可以得到结果。

标签: javascript promise generator co


【解决方案1】:

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

您必须使用co( 调用来包装所有内容。当异步函数落地时,这也会以这种方式运行。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-05
    • 2017-02-06
    • 1970-01-01
    • 1970-01-01
    • 2018-01-05
    • 2018-12-02
    • 2016-01-08
    相关资源
    最近更新 更多