我注意到setTimeout(function, milliseconds)
当在函数中间使用时,只有在函数结束后才会执行,无论给定的调整如何,
例如:
function doStuff(){
var begin = (new Date()).getTime();
console.log(begin);
setTimeout(function(){console.log("Timeout");},100);
doWork(4000);
var end = (new Date()).getTime();
console.log(end);
console.log("diff: "+(end-begin));
}
function doWork(num){
for(;num>0;--num) console.log("num");
}
doStuff();

上面的代码将超时设置为100毫秒,但只有在所有函数完成后才会调用,超过100毫秒,
我的问题是:
为什么会这样?
我如何确保正确的时间安排?
答案 0 :(得分:2)
JavaScript并不是先发制人:它首先完成它正在做的事情,然后再查看队列中发布的下一个任务(为异步执行提交的函数)。因此,即使超时到期,这也不会影响当前运行的代码 - 它不会被中断。只有当当前正在运行的函数堆栈全部返回且没有任何内容需要运行时,JavaScript才会检查是否有要执行的超时请求,或队列中的其他任何内容。
来自"Concurrency model and Event Loop" on MDN:
队列
JavaScript运行时包含一个消息队列,它是要处理的消息列表。功能与每条消息相关联。当堆栈为空时,将从队列中取出一条消息并进行处理。处理包括调用相关函数(从而创建初始堆栈帧)。当堆栈再次变空时,消息处理结束。
事件循环
事件循环的名称取决于它通常如何实现,通常类似于:
如果当前没有消息,while(queue.waitForMessage()){ queue.processNextMessage(); }
queue.waitForMessage
会同步等待消息到达。"运行到完成"
在处理任何其他消息之前,将完全处理每条消息。这在推理程序时提供了一些不错的属性,包括每当函数运行时,它都不能被抢占并且在任何其他代码运行之前完全运行(并且可以修改函数操作的数据)。这与C不同,例如,如果一个函数在一个线程中运行,它可以在任何时候停止在另一个线程中运行一些其他代码。
此模型的缺点是,如果消息完成时间过长,则Web应用程序无法处理用户交互,例如单击或滚动。浏览器使用&#34来缓解这个问题;脚本运行时间过长"对话。遵循的一个好习惯是使消息处理简短,如果可能,将一条消息剪切成几条消息。
要使代码同时运行,您可以使用Web Workers。 Web Workers在不同的线程中运行脚本。