node.js redis异步性质令人困惑

时间:2015-11-20 09:10:53

标签: javascript node.js redis

我正在使用如下所示的redis,因为on('message')似乎被异步调用而遇到麻烦?

var subscriber = redis.createClient(port, host);
subscriber.subscribe('something');

subscriber.on('message', function(channel, message) {
    console.log('got message');

    // I use generator here

    var generator = myGenerator();
    var waitFunciton = generator.next().value;

    waitFunction(function(err, data) {

        var result = generator.next().value;

        // do something with result
        console.log('returning result');
    });

});

我希望看到

'got message'  
'returning result'
'got message'  
'returning result'

按顺序。

有时我会看到以下内容

'got message'
'got message'
'returning result'

查看缺少的“返回结果”,程序卡住了。

我该如何修复程序?

**编辑**

var myGenerator = function* (arg) {
    main = {};
    main.messenger = new Backbone.Model();

    // performs something heavy

    // at the end of the heavy work,
    // main.messenger.trigger('done') is called

    _.extend(main, {
        wait: function (callback) {
            return main.messenger.once('done', callback);

        }
    });

    yield _.bind(main.wait, main);

    // since I have results at hand I'm returning result next time when I'm called

    var result;

    return result;

}

1 个答案:

答案 0 :(得分:0)

您的代码卡住了,因为您在第一次调用done后仅触发myGenerator一次。 next()调用不会使生成器函数从开始执行,因此callback log('returning result')只执行一次。

您可以修改main.wait函数以检查是否已经完成了大量计算并立即调用回调。

var myGenerator = function* (arg) {
    main = {};
    main.messenger = new Backbone.Model();

    // performs something heavy

    // at the end of the heavy work,
    // main.messenger.trigger('done') is called
    // main.messenger.set('computationDone', true);

    _.extend(main, {
        wait: function (callback) {
            if (main.messenger.get('computationDone') === true){
                 callback(); //filled with some data of course
            } else {
                return main.messenger.once('done', callback);
            }
        }
    });

    yield _.bind(main.wait, main);

    // since I have results at hand I'm returning result next time when I'm called

    var result;

    return result;
}