0

I'm having trouble trying to return promise results as a yield back to the original caller.

store.js

module.exports = {
    find: function *(storeRequest){
        if(!_gateway){
            _gateway = realGateway;
        }

        storeResponse.http.statusCode = 200;

        var stores = _gateway.find(storeRequest.id).next().value; // I want to be able to get the stores array back here ultimately by calling next() like I am trying to do here

        console.log(stores[0]); 
        //yield storeResponse;
    }
};

storeGateway.js

    module.exports = {
        find: function *(id){
            var stores = [];
            var entity;

            database.find.then(function(foundStores){

                    entity = testUtil.createStore(foundStores[0].id, foundStores[0].name);
                    console.log("ENTITY:");
                    console.log(entity);

                    stores.push(entity);

                    console.log("STORES[0]:");
                    console.log(stores[0]);

// I am getting the results here successfully so far when I console.log(stores[0])!  But now I want to return stores now from here and yield the array so it propogates up to the caller of storeGateway's find()
                   // yield entity; --- this doesn't work because I think I'm in the promise then scope
                }
            );

            //yield entity;  -- and this definitely won't work because it's not in the promise callback (then)
        }
    };

database.js

var co = require('co');
var pg = require('co-pg')(require('pg'));
var config = require('./postgreSQL-config');

var database = module.exports = {};

var _id;
var _foundStores;

database.find = co(function* poolExample(id) {

        var query = "Select id, name from stores";

        try {
            var connectionResults = yield pg.connectPromise(config.postgres);
            var client = connectionResults[0];
            var done = connectionResults[1];

            var result = yield client.queryPromise(query);
            done();

            console.log("PRINTING ROWS:");
            console.log(result.rows[0]);

            _foundStores = yield result.rows;

        } catch(ex) {
            console.error(ex.toString());
        }

        console.log("RESULTS!:");
        console.log(_foundStores);

        return _foundStores;
    });

I'm getting data printed on every console.log you see above. I just don't know how to return the stores from the storeGateway's find() method since it's receiving the stores array in the promise result (in the .then()) and I need to be able to yield that back upstream.

(see my comment in code, I'm trying to return the found stores in the promise's then back upstream from my store.js's find generator function).

Bergi
  • 513,640
  • 108
  • 821
  • 1,164
PositiveGuy
  • 11,583
  • 13
  • 50
  • 102
  • `_foundStores = yield result.rows;` makes no sense if you previously already did access `result.rows[0]`. Why are you doing this? What is `rows[0]` in the log (or: what do you expect it to be)? – Bergi Sep 10 '15 at 12:23
  • Yea that previous was just testing – PositiveGuy Sep 10 '15 at 19:39

2 Answers2

1

The point of using generators and co is that you can yield promises to the coroutine runner and get their results back, so that you don't have to use then.

Start by making find a method in your database.js:

database.find = co.wrap(function* poolExample(id) {
//                ^^^^^
    …
});

Then in storeGateway.js you should be doing

module.exports = {
    find: function*(id) {
        var foundStores = yield database.find(id);
        var entity = testUtil.createStore(foundStores[0].id, foundStores[0].name);
        console.log("ENTITY:", entity);
        var stores = [entity];
        console.log("STORES[0]:", stores[0]);
        return stores;
    }
};

(maybe wrap the generator function in co.wrap(…)).

Then in store.js you can do

module.exports = {
    find: co.wrap(function*(storeRequest) {
        if (!_gateway) _gateway = realGateway;
        storeResponse.http.statusCode = 200;
        var stores = yield* _gateway.find(storeRequest.id);
        // or        yield _gateway.find(storeRequest.id); if you did wrap it and it
        //                                                 returns a promise, not a generator
        console.log(stores[0]);
        return stores;
    })
};
Bergi
  • 513,640
  • 108
  • 821
  • 1,164
  • Thanks yea I am still a newbie on the generators, will give it a try, thanks! – PositiveGuy Sep 10 '15 at 12:33
  • getting object is not a function on the var foundStores = yield database.find(); – PositiveGuy Sep 10 '15 at 12:54
  • yea it's not working I keep getting object is not a function again after I wrapped store.js with co too – PositiveGuy Sep 10 '15 at 13:06
  • Ah, I mistook `co` for `co.wrap`. I didn't realise that you did really create `database.find` as a promise, not a promise-returning function. Or didn't you intend to do that? – Bergi Sep 10 '15 at 13:15
  • No idea about co.wrap – PositiveGuy Sep 10 '15 at 13:23
  • Just check my edit to my answer. Maybe you also want to change `co()` to `co.wrap()` in your database.js, so that you can invoke `database.find(id)` – Bergi Sep 10 '15 at 13:25
  • I did have a look at [co-pg](https://www.npmjs.com/package/co-pg), but their example is quite different from your usage. Most of all because they didn't declare any method. – Bergi Sep 10 '15 at 13:31
  • If they didn't declare a method then I wondered how anyone would call it. Maybe you can explain? – PositiveGuy Sep 10 '15 at 13:37
  • Will try the co-wrap in about a half hour – PositiveGuy Sep 10 '15 at 13:38
  • ok got it working with playing around with it like nuts. One more question. How can I pass an id in so that I can use that in my query select statement? Right now I'm just setting country.find = co(....) in database.js, so how can I pass in an id so that I can use it inside co()? – PositiveGuy Sep 10 '15 at 14:30
  • As I suggested, you don't want to use `co()`, which creates a promise not a function – Bergi Sep 10 '15 at 14:45
  • If it were not for your help today I would have spent probably many more hours on this. Thanks a lot! – PositiveGuy Sep 10 '15 at 16:16
-1

There are two ways to do this. You either receive a call back parameter into your function and call it when the promise is resolved (inside your then function) or better, return the result of then. then() itself returns a promise and whatever you return from with in the function are available to the subsequent functions chained to the promise, so if you do this

return database.find.then(function(foundStores){
       entity = testUtil.createStore(foundStores[0].id, foundStores[0].name);
       console.log("ENTITY:");
       console.log(entity);
       stores.push(entity);    
       console.log("STORES[0]:");
       console.log(stores[0]);
       return stores[0];
}

then you could do gateway.find().then(function(stores){}) and stores would be what you returned i.e. stores[0].

Sasikanth Bharadwaj
  • 1,437
  • 1
  • 11
  • 10