Node.js 如何用新的Promise()替换Promise.defer

Node.js 如何用新的Promise()替换Promise.defer,node.js,promise,Node.js,Promise,所以我看到,Promise.defer现在已经被弃用了,我们现在应该使用newpromise。我不知道如何在这个例子中做到这一点 var Promise = require('bluebird'); var interval; var rollDice = function (resolver) { console.log("rolling"); if (Math.floor(Math.random() * 10) == 7) { clearInterval(interval)

所以我看到,
Promise.defer
现在已经被弃用了,我们现在应该使用
newpromise
。我不知道如何在这个例子中做到这一点

var Promise = require('bluebird');
var interval;

var rollDice = function (resolver) {
  console.log("rolling");
  if (Math.floor(Math.random() * 10) == 7) {
    clearInterval(interval);
    resolver.resolve();
  }
}

var rollTill7 = function (ms) {
    var resolver = Promise.defer();
    interval = setInterval(function(){rollDice(resolver);},ms);
    return resolver.promise;
}

rollTill7(100).then(function(){
    console.log("rolled a 7");
});

一般来说,建议远离旧的延迟模型,因为您希望承诺的创建者负责解决或拒绝它-这只会使控制流更容易遵循。您不希望将解决或拒绝的责任转交给其他代码

如果解决或拒绝的决策涉及外部代码(例如
rollDice()
函数),则它可以返回用于解决或拒绝的信息。例如,在您的代码示例中,可以这样做

请注意,
rollDice()
函数现在只是一个骰子滚动函数,它告诉您是否滚动了特定数量的骰子。然后,另一个函数使用它来确定控制流,而不是将控制流放入骰子滚动函数本身

var rollDice = function() {
  console.log("rolling");
  return Math.floor(Math.random() * 10) + 1;
}

var rollTillNum = function(num, ms) {
    return new Promise(function(resolve) {
        var interval = setInterval(function(){
            if (rollDice() === num) {
               resolve();
               clearInterval(interval);
            }
        }, ms);
    });
}

rollTillNum(7, 100).then(function(){
    console.log("rolled a 7");
});
更改摘要:

  • 承诺管理是自包含的,没有委托给其他功能(使代码的逻辑更易于遵循),这是使用新的承诺构造函数而不是延迟构造函数的主要原因之一
  • interval
    变量现在包含在本地范围内
  • rollDice()
    函数现在是通用函数,因此可以在其他上下文中使用
  • rollDice()
    现在返回基于1的值,而不是基于0的值(因为骰子就是这样工作的)
  • 现在是
    rollTillNum()

  • 虽然上述解决方案更通用(使用外部函数提供是否应解决问题的反馈),但在这种特定情况下,如果您甚至不需要外部可用的
    rollDice()
    函数,则可以将其完全包含在
    rollTillNum()
    函数中:

    var rollTillNum = function(num, ms) {
        return new Promise(function(resolve) {
            var interval = setInterval(function(){
                if ((Math.floor(Math.random() * 10) + 1) === num) {
                   resolve();
                   clearInterval(interval);
                }
            }, ms);
        });
    }
    
    rollTillNum(7, 100).then(function(){
        console.log("rolled a 7");
    });
    

    以下是制作成工作演示的上述代码:

    document.getElementById(“roll”).addEventListener(“单击”,函数(){
    var start=Date.now();
    rollTillNum(7100)。然后(函数(cnt){
    var经过=((Date.now()-start)/1000).toFixed(1);
    日志(“需要“+经过+”秒和“+cnt+”转鼓才能转鼓7”);
    });
    });
    var rollDice=函数(){
    控制台。日志(“滚动”);
    返回Math.floor(Math.random()*10)+1;
    }
    var rollTillNum=函数(num,ms){
    返回新承诺(函数(解析){
    var-cntr=0;
    var interval=setInterval(函数(){
    ++碳纳米管;
    if(rollDice()==num){
    解决(cntr);
    间隔时间;
    }
    },ms);
    });
    }
    函数日志(x){
    var div=document.createElement(“div”);
    div.innerHTML=x;
    文件.正文.附件(div);
    }
    
    滚7
    

    试试这个

    var rollDice = function (resolve) {
      console.log("rolling");
      if (Math.floor(Math.random() * 10) == 7) {
        clearInterval(interval);
        resolve();
      }
    }
    
    var rollTill7 = function (ms) {
        return new Promise(function(resolve) {
            interval = setInterval(function() {
                rollDice(resolve);
            }, ms);
        });
    }
    

    使用
    newpromise(constructorFn)
    的直接等效方法是在
    constructorFn
    中写入
    interval=setInterval(…)
    ,并将constructorFn的resolve参数传递给
    rollDice()
    ,而不是原始的延迟对象

    var Promise = require('bluebird');
    var interval;
    
    var rollDice = function (resolve) {
      console.log("rolling");
      if (Math.floor(Math.random() * 10) == 7) {
        clearInterval(interval);
        resolve();
      }
    };
    
    var rollTill7 = function (ms) {
        return new Promise(function(resolve, reject) {
            interval = setInterval(function() {
                rollDice(resolve);
            }, ms);
        });
    };
    
    rollTill7(100).then(function() {
        console.log("rolled a 7");
    });
    
    如果
    interval
    rollDice()
    也被移动到promise的构造函数中,那么解决方案会变得更加整洁。不仅从外部名称空间中删除了两个成员,而且还避免了传递
    resolve
    的需要-由于关闭,
    rollDice()
    可以访问它

    var Promise = require('bluebird');
    
    var rollTill7 = function (ms) {
        return new Promise(function(resolve, reject) {
            var interval;
            var rollDice = function () {
              console.log("rolling");
              if (Math.floor(Math.random() * 10) == 7) {
                clearInterval(interval);
                resolve();
              }
            };
            interval = setInterval(rollDice, ms);
        });
    };
    
    rollTill7(100).then(function() {
        console.log("rolled a 7");
    });
    

    更进一步,您可能会选择将
    rollDice()
    作为匿名函数移动到
    setInterval
    表达式中。这将避免命名函数的问题,即它不只是“掷骰子”,它还可以解决问题。

    接受这一答案,因为我很欣赏改进的作用域解决方案。@GroovyDotCom-我不认为这两种解决方案都是理想的。第一种方法仍然将解决承诺的责任委托给外部函数,这是完全不必要的,并且会使理解和遵循代码的能力变得复杂,尤其是在更大的代码体中。首先,不使用延迟的方法的全部目的是将解决和拒绝责任保持在本地,而不是将其转移到其他地方。第二个示例很方便,但它隐藏了
    rollDice()
    函数,因此无法使用elsewhere@GroovyDotCom-虽然在这个特定示例中隐藏
    rollDice()
    函数可能没问题,但更一般的情况是,该函数在外部声明,因为它在其他地方使用(否则,它甚至不需要是一个函数)。您可以在这里看到其他答案之一,以获得更一般的解决方案。@jfriend00,我同意所有这些。为了演示“如何用新承诺替换承诺。延迟()”的原则,我决定尽可能地坚持OP的原始方法。实际上,我会按照你的建议做很多事情。谢谢Roamer。这是一个艰难的决定,但经过编辑,我认为Jfriend现在有了完整的答案。没有理由使用
    rollDice()
    函数必须知道某个承诺的任何信息,因此没有理由将承诺的解析委托给承诺构造函数之外的人。
    rollDice()
    生命中的任务是进行随机滚动。
    rollTill7()
    中的代码可以使用
    rollDice()的返回值
    然后
    rollTill7()
    可以确定是否达到了所需的数量,以及是否应该解决承诺。如果承诺是在同一代码块中创建和解决的,则最容易理解。@jfriend00,你是对的。我只是替换