javascript - Can't figure out how to use yield with async request - Stack Overflow

I'm somewhat new to node, and I'm pletely new to koa.I'm trying to use generators to d

I'm somewhat new to node, and I'm pletely new to koa. I'm trying to use generators to do async web requests to an API, but I can't figure out how to put all the pieces together.

As a note, I'm using bluebird because I saw some examples do that, and it seemed like a good idea. If there's an easier way to do what I want without bluebird, that's totally fine as well.

In my module:

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

and I'm calling it like this:

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

When I look in my console, I see:

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

I know my code is kind of all over the place, but I've worked on it for hours and I'm still no closer to fixing it.

Thanks!

I'm somewhat new to node, and I'm pletely new to koa. I'm trying to use generators to do async web requests to an API, but I can't figure out how to put all the pieces together.

As a note, I'm using bluebird because I saw some examples do that, and it seemed like a good idea. If there's an easier way to do what I want without bluebird, that's totally fine as well.

In my module:

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

and I'm calling it like this:

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

When I look in my console, I see:

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

I know my code is kind of all over the place, but I've worked on it for hours and I'm still no closer to fixing it.

Thanks!

Share Improve this question asked Dec 23, 2014 at 16:11 snollygollysnollygolly 1,8862 gold badges17 silver badges32 bronze badges 0
Add a ment  | 

3 Answers 3

Reset to default 4

Please don't call promisifyAll in runtime code: it's unnecessary, clutters application logic, doesn't belong there and is very very slow.

You need to mark the method as coroutine, otherwise it's just a generator.

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.").get(0);
    console.log(response.statusCode);
    return response;
});

The coroutines returns a promise which you can consume with another coroutine or just use it as a promise. Since you are already using generators, you might as well use another coroutine:

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

Calling a generator from .then is not going to e close to working. Calling a generator merely returns its iterator and does nothing with it. What you want is something like (untested):

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

You don't need to do the .then. That is Koa's job. It will get the promise you yielded, wait for it resolve, pass back the resolved value as the parameter to iterator.next(), which bees your variable result, and the function will continue to the next yield (or the end of the function).

However, in your case, it's not clear that you want to yield the response as you are doing in the last line. For one thing, you have to yield promises, so this will probably cause a Koa run-time error. I suspect you want something like just

this.body = response;

You might consider using an existing request wrapper, such as co-request build to work with the co library which koa is build upon.

In koa you would do something like:

// server.js
var request = require('co-request');

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

});

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744504204a4577608.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信