var wait = function (milliseconds) {
var returnCondition = false;
window.setTimeout(function () { returnCondition = true; }, milliseconds);
while (!returnCondition) {};
};
我知道有很多帖子说明为什么不尝试在Javascript中实现wait()
或sleep()
函数。因此,这不是为了使其可用于实现目的,而是使其用于概念证明。
尝试
console.log("Starting...");wait(3000);console.log("...Done!");
冻结我的浏览器。为什么wait()
似乎永远不会结束?
编辑:感谢到目前为止的答案,我不知道while循环从不允许执行任何其他代码。
那么这会起作用吗?
var wait = function (milliseconds) {
var returnCondition = false;
var setMyTimeOut = true;
while (!returnCondition) {
if (setMyTimeOut) {
window.setTimeout(function() { returnCondition = true; }, milliseconds);
setMyTimeOut = false;
}
};
return;
};
答案 0 :(得分:5)
JavaScript在单个线程中执行。只有当执行路径退出时,才能开始另一个执行路径。因此,当您启动wait(3000)
时,会发生以下情况:
returnCondition
设置为false
每个<script>
标记,每个事件都被处理,每次超时(以及浏览器时的UI刷新)都会启动一个单独的执行路径。因此,3000的超时不能保证在3000ms内运行,但在发动机“空闲”的3000ms之后的任何时间都可以保证。
wait
函数永远不会退出,因此您的脚本的执行路径永远不会结束,并且预定的超时时间永远不会到来。
编辑:
这意味着,一旦<script>
标记开始,或者Node.js已经开始执行JavaScript文件,执行必须在其他任何事情发生之前到达底部。如果函数是由于事件或超时而启动的,那么该函数需要在其他任何事情发生之前退出。
<script>
console.log("script top");
function theTimeout() {
console.log("timeout top");
// something long
console.log("timeout bottom");
}
setTimeout(theTimeout, 0);
setTimeout(theTimeout, 0);
console.log("script bottom");
</script>
这里有三条执行路径。第一个是<script>
标签:它首先打印“脚本顶部”,安排两个超时(“立即”),然后打印“脚本底部”,然后到达<script>
的结尾而翻译是空闲的。这意味着它有时间执行另一个执行路径,并且有两个超时正在等待,因此它选择其中一个并开始执行它。当它正在执行时,再也没有其他任何东西可以执行(甚至是UI更新);另一个超时,即使它也是“立即”调度,也要等到第一个超时的执行路径结束。当它发生时,第二次超时结束,它也会被执行。
答案 1 :(得分:2)
JavaScript是单线程的。当您调用setTimeout时,作为参数传入的方法将被放置到异步调用堆栈中。这意味着块中的下一行代码在setTimeout调用之后立即执行,并且作为参数传入的函数将在wait方法退出后执行。
你的while循环正在等待一个在wait函数运行时永远不会发生的情况,因为设置你的标志的函数在wait函数完成之前不会运行。
实施等待的正确方法是:
var wait = function (milliseconds, onEnd) {
window.setTimeout(function () { onEnd(); }, milliseconds);
};
wait(1000, function(){alert('hi')});
这里传入一个回调函数,该函数将在超时后执行。
如果您有多个异步样式调用,则可以使用promises。 Promise将使您的代码易于阅读,并且可以轻松地将多个异步调用链接在一起。图书馆员有很好的承诺:JQuery内置了$ .Deferred,但是如果编写node.js代码,可以使用Q.
承诺样式实现看起来像这样:
var wait = function (milliseconds) {
var onEnd = null;
window.setTimeout(function () { onEnd(); }, milliseconds);
return {
then: function(action){
onEnd = action;
}
}
};
wait(1000).then(function(){alert('hi')});
https://api.jquery.com/jquery.deferred/ https://github.com/kriskowal/q
下面的书帮助我理解了这个主题:
Async JavaScript:Trevor Burnham用更少的代码构建更具响应性的应用程序 https://pragprog.com/book/tbajs/async-javascript