【问题标题】:Exiting Final Promise Scope from Within a Generator Function从生成器函数中退出最终承诺范围
【发布时间】:2015-09-10 05:04:04
【问题描述】:

我在尝试将 Promise 结果作为收益返回给原始调用者时遇到了麻烦。

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 上都打印了数据。我只是不知道如何从 storeGateway 的 find() 方法返回存储,因为它在 promise 结果中接收存储数组(在 .then() 中),我需要能够将其返回到上游。

(请参阅我在代码中的注释,我正在尝试从我的 store.js 的 find 生成器函数返回 promise 中找到的商店,然后返回上游)。

【问题讨论】:

  • 如果您之前已经访问过result.rows[0]_foundStores = yield result.rows; 毫无意义。你为什么做这个?日志中的rows[0] 是什么(或者:你期望它是什么)?
  • 是的,以前只是测试

标签: javascript node.js promise generator co


【解决方案1】:

使用生成器和co 的重点是您可以yield 向协程运行器承诺并获取其结果,这样您就不必使用then

首先在您的database.js 中创建find 方法:

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

【讨论】:

  • 谢谢,我还是发电机的新手,会试一试,谢谢!
  • 获取对象不是 var foundStores = yield database.find(); 上的函数
  • 是的,它不工作,在我用 co 包装 store.js 之后,我不断得到 object is not a function
  • 啊,我把co 误认为co.wrap。我没有意识到您确实将database.find 创建为一个承诺,而不是一个承诺返回函数。还是您不打算这样做?
  • 不知道 co.wrap
【解决方案2】:

有两种方法可以做到这一点。您可以在函数中接收回调参数并在 promise 解决时调用它(在您的 then 函数中),或者更好地返回 then 的结果。 then() 本身返回一个promise,并且函数中返回的任何内容都可用于链接到promise 的后续函数,所以如果你这样做

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){}) 并且 stores 就是你返回的,即 stores[0]。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-29
    • 2014-11-06
    • 1970-01-01
    • 2014-10-22
    • 1970-01-01
    • 2019-06-13
    • 1970-01-01
    • 2022-09-27
    相关资源
    最近更新 更多