所以我看到Promise.defer
现已弃用,我们现在应该使用new Promise
。但是,对于这个例子,我不知道如何做到这一点?
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");
});
答案 0 :(得分:10)
一般情况下,建议远离旧的延迟模型,因为您希望承诺的创建者负责解决或拒绝它 - 这只会使控制流更容易理解。您不想传递解决或拒绝其他代码的责任。
如果决定解决或拒绝外部代码(例如您的rollDice()
函数),则它可以返回用于解析或拒绝的信息。例如,在您的代码示例中,可以这样做。
请注意,rollDice()
函数现在只是一个骰子滚动函数,它告诉您是否滚动了特定数量的not。然后由另一个函数使用它来确定控制流,而不是将控制流放在骰子滚动功能本身中。
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开始的值(因为这是骰子的工作方式)。rollTill7()
,而不是现在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("click", function() {
var start = Date.now();
rollTillNum(7, 100).then(function(cnt) {
var elapsed = ((Date.now() - start) / 1000).toFixed(1);
log("It took " + elapsed + " seconds and " + cnt + " rolls to roll a 7");
});
});
var rollDice = function() {
console.log("rolling");
return Math.floor(Math.random() * 10) + 1;
}
var rollTillNum = function(num, ms) {
return new Promise(function(resolve) {
var cntr = 0;
var interval = setInterval(function(){
++cntr;
if (rollDice() === num) {
resolve(cntr);
clearInterval(interval);
}
}, ms);
});
}
function log(x) {
var div = document.createElement("div");
div.innerHTML = x;
document.body.appendChild(div);
}

<button id="roll">
Roll a 7
</button><br><br>
&#13;
答案 1 :(得分:1)
试试这个
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);
});
}
答案 2 :(得分:1)
使用new Promise(constructorFn)
的直接等效项是在interval = setInterval(...)
内写constructorFn
并将constructorFn的resolve参数传递给rollDice()
而不是原始的Deferred对象。
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
表达式中。这将使命名函数的一个问题侧重于它不仅仅是&#34;滚动骰子&#34; - 它也解决了。