无法弄清楚如何使用async请求使用yield

时间:2014-12-23 16:11:31

标签: javascript node.js generator bluebird koa

我对节点有点新意,而且我对koa完全不熟悉。我正在尝试使用生成器来对API执行异步Web请求,但我无法弄清楚如何将所有部分组合在一起。

作为一个注释,我正在使用蓝鸟,因为我看到一些例子这样做,这似乎是一个好主意。如果有一种更简单的方法可以在没有蓝鸟的情况下做我想要的事情,那也完全没问题。

在我的模块中:

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}

我知道我的代码遍布整个地方,但我已经工作了好几个小时,而且我仍然没有接近修复它。

谢谢!

3 个答案:

答案 0 :(得分:4)

请不要在运行时代码中调用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;
});

协同程序返回一个可以与另一个协同程序一起使用的承诺,或者只是将其用作承诺。由于您已经在使用生成器,因此您可以使用另一个协程:

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

答案 1 :(得分:1)

.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。那是Koa的工作。它将获得您所产生的承诺,等待它解决,将已解析的值作为参数传递给iterator.next(),这将成为您的变量result,函数将继续到下一个yield }(或函数的结尾)。

但是,在您的情况下,您不希望像在最后一行中那样产生响应。首先,你必须产生承诺,所以这可能会导致Koa运行时错误。我怀疑你想要像

这样的东西
this.body = response;

答案 2 :(得分:0)

您可以考虑使用现有的request包装器(例如co-request版本)来处理构建cokoa库。

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

});