【问题标题】:Can't figure out how to use yield with async request无法弄清楚如何将 yield 与异步请求一起使用
【发布时间】:2014-12-23 16:11:31
【问题描述】:

我对 node 有点陌生,对 koa 完全陌生。我正在尝试使用生成器对 API 执行异步 Web 请求,但我不知道如何将所有部分组合在一起。

作为说明,我使用 bluebird 是因为我看到了一些例子,这似乎是个好主意。如果有一种更简单的方法可以在没有蓝鸟的情况下做我想做的事,那也很好。

在我的模块中:

plugin.searchForItem = function * (name) {
  Promise = require('bluebird');
  request = Promise.promisifyAll(require('request'));
  console.log("making request");
  yield request.getAsync('http://apisitegoeshere.com/apicall').then(function * (result) {
    var response = result[0];
    var body = result[1];
    console.log(response.statusCode);
    yield response;
  });
};

我这样称呼它:

search.searchForShow = function (name) {
  data = this.plugins[0].searchForItem(name);
  console.log("search returned: " + data);
  console.log("search returned2: " + JSON.stringify(data.next()));
  console.log("search returned3: " + JSON.stringify(data.next()));
  return data;
};

当我查看控制台时,我看到:

search returned: [object Generator]
making request
search returned2: {"value":{"isFulfilled":false,"isRejected":false},"done":false}
search returned3: {"done":true}

我知道我的代码到处都是,但我已经研究了几个小时,但我仍然没有接近修复它。

谢谢!

【问题讨论】:

    标签: javascript node.js generator bluebird koa


    【解决方案1】:

    请不要在运行时代码中调用promisifyAll:这是不必要的,混乱的应用程序逻辑,不属于那里并且非常非常慢。

    你需要将方法标记为协程,否则它只是一个生成器。

    var Promise = require("bluebird");
    // Assumes request is promisified else where, like in your init file
    var request = require("request");
    
    plugin.searchForItem = Promise.coroutine(function* (name) {
        var response = yield request.getAsync("http://www.google.com").get(0);
        console.log(response.statusCode);
        return response;
    });
    

    协程返回一个 Promise,您可以将其与另一个协程一起使用,也可以将其用作 Promise。既然你已经在使用生成器了,不妨使用另一个协程:

    search.searchForShow = Promise.coroutine(function* (name) {
      var data = yield this.plugins[0].searchForItem(name);
      console.log("search returned: " + data);
      return data;
    });
    

    【讨论】:

    • 非常感谢!这非常有帮助,而且就像一个魅力。我按照建议将我的 promisifyAll 部分移动到了一个 init 文件中。
    【解决方案2】:

    .then 调用生成器不会接近工作。调用生成器只是返回它的迭代器,而不用它做任何事情。你想要的是(未经测试):

    plugin.searchForItem = function * (name) {
      Promise = require('bluebird');
      request = Promise.promisifyAll(require('request'));
      console.log("making request");
      var result = yield request.getAsync('http://apisitegoeshere.com/apicall');
      var response = result[0];
      var body = result[1];
      console.log(response.statusCode);
      yield response;
    };
    

    您无需执行.then。那是科亚的工作。它会得到你产生的promise,等待它resolve,把resolved的值作为参数传回iterator.next(),变成你的变量result,函数会继续到下一个yield(或结束函数)。

    但是,在您的情况下,不清楚您是否要像在最后一行中所做的那样产生响应。一方面,你必须产生 Promise,所以这可能会导致 Koa 运行时错误。我怀疑你想要的只是

    this.body = response;
    

    【讨论】:

      【解决方案3】:

      您可能会考虑使用现有的 request 包装器,例如 co-request 构建来使用 koa 构建的 co 库。

      在 koa 中你会做这样的事情:

      // server.js
      var request = require('co-request');
      
      app.use(function *(){
          try{
              var result = yield request('http://apisitegoeshere.com/apicall');       
              this.body = result.body;
          }
          catch(err){
              this.throw(500);
          }
      
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-05-08
        • 2021-06-25
        • 2010-11-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-18
        相关资源
        最近更新 更多