【问题标题】:bluebird coroutine no executing at all蓝鸟协程根本没有执行
【发布时间】:2015-11-14 19:34:30
【问题描述】:

我正在尝试实现剪刀石头布游戏的 CLI 版本。我正在使用查询器模块来处理 IO。我的主要功能如下所示:

RockPaperScissors.prototype.gameLoop = function()
{
var x;
var Promise = require('bluebird');


//simple promise test
//this.playGame().then(function(){ console.log("The end");});

Promise.coroutine(function*()
{

    //for(x=0;x<this.maxTurns;x++)
    //{
        console.log('Printing '+ x.toString());
        var action = yield this.playGame();
    //}    

    if(this.playerScore > this.serverScore) { console.log('Player wins match');} else {console.log('Server wins match');  }    

});
};

exports.RockPaperScissors = RockPaperScissors;

playGame() 函数返回一个使用 new Promise() 做出的承诺。如果我这样做:

this.playGame().then(function(){ console.log("The end");});

承诺正确执行。但是,当在 Promise.coroutine() 中使用时,不会执行任何操作。我在这里错过了什么?

这是 playGame() 函数的代码:

RockPaperScissors.prototype.playGame = function()
{

    var inq = require('inquirer');  
    var rand = require('random-js');
    var _ = require('lodash');
    var promise = require('bluebird');

    //make possibilities local
    var possibilities = this.possibilities;

    console.log ('------------------ Stats ----------------');
    console.log ('Player: ' +this.playerScore+'  Server: '+this.serverScore);
    console.log ('-----------------------------------------');

    var question1 ={
        type:'rawlist',
        name:'option',
        message:'Please choose Rock, paper or scissors:',
        choices:['Rock','Paper','Scissors']
    };

    return new promise(function(resolve,reject)
    {
       inq.prompt([question1],function(answers)
       {
            console.log('You chose '+answers.option);
            var playerObject = answers.option;
            //random with Mersenne Twister API
            var r = new rand(rand.engines.mt19937().autoSeed());
            var myPlay =r.integer(0,2);
            var serverObject ='';
            switch(myPlay)
            {
                case 0:
                    serverObject='Rock';
                    break;
                case 1:
                    serverObject ='Paper';
                    break;
                case 2:
                    serverObject='Scissors';
                    break;
            }

            var result='', action='';
            //choose winner by using a lodash function!
            _.forEach(possibilities,function(e){
                if (e[0]==serverObject && e[1] ==playerObject) 
                {
                     result=e[2];
                     action=e[3];
                }
            });

            console.log('I chose ' + serverObject+ "\n")
            console.log (result);

            if (action=='win') {this.playerScore++;}
            if (action=='lose'){this.serverScore++;}
            resolve(action);
        });
    });
};

【问题讨论】:

标签: javascript promise command-line-interface bluebird


【解决方案1】:

Promise.coroutine 是一个高阶函数,即它接受一个生成器函数并返回另一个函数,该函数在调用时将返回您正在寻找的承诺。正如@robertklep 所说,您甚至没有调用返回的函数。

相反,您应该将完整的方法包装在Promise.coroutine 中,而不是在方法中调用它。您的代码应如下所示:

var Promise = require('bluebird');

RockPaperScissors.prototype.gameLoop = Promise.coroutine(function*() {
    // simple promise test:
    // yield this.playGame();
    // console.log("The end");

    for (var x=0;x<this.maxTurns;x++) {
        console.log('Printing '+ x.toString());
        var action = yield this.playGame();
    }

    if (this.playerScore > this.serverScore) {
        console.log('Player wins match');
    } else {
        console.log('Server wins match');
    }
});

【讨论】:

  • 嗨,这看起来比我的方法干净得多。为什么这会保留“this”的价值?我只是想了解为什么有时它的对象与预期的对象不同。
  • 因为Promise.coroutine 创建的函数确实使用其this 值调用了生成器函数。
【解决方案2】:

Promise.coroutine() “返回一个可以使用 yield 来产生承诺的函数” (doc),但实际上你并没有调用该函数。

你可能想要这样的东西:

Promise.coroutine(function*() {
...
})();
//^^ calling it

【讨论】:

  • 我必须做一些额外的修改才能让它工作。例如,我必须保存对“this”对象的引用并将其作为参数传递给生成器函数,因为似乎 this 上下文在内部 promise 时会丢失(绑定到不同的值)。我也不得不这样做到 playGame() 函数。我仍然不知道为什么承诺会这样做。
  • @tutiplain bluebird 有一个 bind 方法,您可以使用该方法为函数设置 this。所以像这样:Promise.bind(this).coroutine(function*() { ... }).
  • @robertklep:而是Promise.coroutine(function*() {…}).call(this)。但是请查看我的答案以获得更好的解决方案,该解决方案也可以解决this 问题。
猜你喜欢
  • 2015-09-06
  • 2017-05-27
  • 1970-01-01
  • 2015-04-13
  • 1970-01-01
  • 1970-01-01
  • 2014-10-15
  • 2019-01-24
  • 1970-01-01
相关资源
最近更新 更多