简体   繁体   中英

node.js redis asynchronous nature is confusing

I'm using redis as below, and having trouble because on('message') seems to be called asynchrounously?

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

});

I expect to see

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

in order.

Sometimes I see the following

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

See the missing 'returning result', and program is stuck.

How should I fix the program?

** edit **

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;

}

Your code stucks because you're triggering done only once after first call of myGenerator . next() calls doesn't make the generator function to be executed from start so the callback with log('returning result') executed only once.

You can modify your main.wait function to check if your heavy computation is done already and call the callback immediately.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM