Выход из финальной области обещания из функции генератора

У меня возникли проблемы при попытке вернуть результаты обещаний в качестве возврата к первоначальному звонящему.

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

Я получаю данные, напечатанные на каждом console.log, который вы видите выше. Я просто не знаю, как вернуть хранилища из метода find() storeGateway, так как он получает массив хранилищ в результате обещания (в.then()), и мне нужно иметь возможность вернуть его обратно в восходящем направлении.

(см. мой комментарий в коде, я пытаюсь вернуть найденные магазины в обещании, а затем в обратном направлении от функции генератора поиска моего store.js).

2 ответа

Решение

Смысл использования генераторов и co это то, что вы можете yield обещания бегуна сопрограммы и получить их результаты, так что вам не нужно использовать then,

Начните с создания find метод в вашем database.js:

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

Затем в storeGateway.js ты должен делать

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

(может быть, обернуть функцию генератора в co.wrap(…)).

Затем в store.js ты можешь сделать

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

Есть два способа сделать это. Вы либо получаете параметр обратного вызова в вашу функцию и вызываете его, когда обещание разрешено (внутри вашей функции then), либо лучше, возвращаете результат then. then () сама возвращает обещание, и все, что вы возвращаете с помощью функции, доступно для последующих функций, прикованных к обещанию, так что если вы сделаете это

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

тогда вы можете сделать gateway.find().then(function(stores){}), и store будет тем, что вы вернули, то есть store [0].

Другие вопросы по тегам