有没有比下面的pausecomp函数(取自此处)更好的方法来设计JavaScript中的睡眠?
function pausecomp(millis)
{
var date = new Date();
var curDate = null;
do { curDate = new Date(); }
while(curDate-date < millis);
}
这不是JavaScript中的Sleep的重复-动作之间的延迟;我希望在函数的中间有一个真正的睡眠,而不是在代码执行之前有一段延迟。
首先,应该使用setTimeout和setInterval,因为JavaScript具有回调性质。如果您想使用sleep(),则是控制流或代码架构不正确。
尽管如此,我想我仍然可以帮助实现两个睡眠。
1.我头顶上的假同步跑步:
// A module to do that //dual-license: MIT or WTF [you can use it anyhow and leave my nickname in a comment if you want to]
var _ = (function(){
var queue = [];
var play = function(){
var go = queue.shift();
if(go) {
if(go.a) {
go.f();
play();
}
else
{
setTimeout(play, go.t);
}
}
}
return {
go:function(f){
queue.push({a:1, f:f});
},
sleep:function(t){
queue.push({a:0, t:t});
},
playback:play
}
})();
[也可以自动播放]
// Usage
_.go(function(){
// Your code
console.log('first');
});
_.sleep(5000);
_.go(function(){
// Your code
console.log('next');
});
// This triggers the simulation
_.playback();
2.实际同步运行
有一天,我对它进行了很多思考,我在JavaScript中真正睡觉的唯一想法就是技术。
睡眠函数必须是同步Ajax调用,超时设置为睡眠值。这就是真正睡觉的唯一方法。
首先,应该使用setTimeout和setInterval,因为JavaScript具有回调性质。如果您想使用sleep(),则是控制流或代码架构不正确。
尽管如此,我想我仍然可以帮助实现两个睡眠。
1.我头顶上的假同步跑步:
// A module to do that //dual-license: MIT or WTF [you can use it anyhow and leave my nickname in a comment if you want to]
var _ = (function(){
var queue = [];
var play = function(){
var go = queue.shift();
if(go) {
if(go.a) {
go.f();
play();
}
else
{
setTimeout(play, go.t);
}
}
}
return {
go:function(f){
queue.push({a:1, f:f});
},
sleep:function(t){
queue.push({a:0, t:t});
},
playback:play
}
})();
[也可以自动播放]
// Usage
_.go(function(){
// Your code
console.log('first');
});
_.sleep(5000);
_.go(function(){
// Your code
console.log('next');
});
// This triggers the simulation
_.playback();
2.实际同步运行
有一天,我对它进行了很多思考,我在JavaScript中真正睡觉的唯一想法就是技术。
睡眠函数必须是同步Ajax调用,超时设置为睡眠值。这就是真正睡觉的唯一方法。
这里大多数解决方案的问题是它们倒带堆栈。在某些情况下,这可能是一个大问题。在这个例子中,我展示了如何以不同的方式使用迭代器来模拟真实的睡眠。
在本例中,生成器正在调用自己的next(),因此一旦它启动,它就自己运行了。
var h = a();
h.next().value.r = h; // That's how you run it. It is the best I came up with
// Sleep without breaking the stack!!!
function *a(){
var obj = {};
console.log("going to sleep....2s")
setTimeout(function(){obj.r.next();}, 2000)
yield obj;
console.log("woke up");
console.log("going to sleep no 2....2s")
setTimeout(function(){obj.r.next();}, 2000)
yield obj;
console.log("woke up");
console.log("going to sleep no 3....2s")
setTimeout(function(){obj.r.next();}, 2000)
yield obj;
console.log("done");
}
对于浏览器,我同意使用setTimeout和setInterval。
但是对于服务器端代码,它可能需要一个阻塞函数(例如,这样可以有效地进行线程同步)。
如果您正在使用Node.js和Meteor,您可能遇到了在光纤中使用setTimeout的限制。下面是服务器端睡眠的代码。
var Fiber = require('fibers');
function sleep(ms) {
var fiber = Fiber.current;
setTimeout(function() {
fiber.run();
}, ms);
Fiber.yield();
}
Fiber(function() {
console.log('wait... ' + new Date);
sleep(1000);
console.log('ok... ' + new Date);
}).run();
console.log('back in main');
参见:Node.js光纤,睡眠
这里的大多数答案都是错误的,或者至少是过时的。没有理由JavaScript必须是单线程的,事实上也不是。今天,所有主流浏览器都支持工人。在此之前,Rhino和Node.js等其他JavaScript运行时支持多线程。
“JavaScript是单线程的”不是有效答案。例如,在工作线程中运行睡眠函数不会阻止UI线程中运行的任何代码。
在支持生成器和yield的较新运行时中,可以在单线程环境中为sleep函数带来类似的功能:
// This is based on the latest ES6 drafts.
// JavaScript 1.7+ (SpiderMonkey/Firefox 2+) syntax is slightly different
// Run code you want to sleep here (omit star if using JavaScript 1.7)
function* main(){
for (var i = 0; i < 10; i++) {
// To sleep for 10 milliseconds 10 times in a row
yield 10;
}
yield 5;
console.log('I just slept 5 milliseconds!');
}
// Resume the given generator after ms milliseconds
function resume(ms, generator){
setTimeout(function(){
// Omit .value if using JavaScript 1.7
var nextSleep = generator.next().value;
resume(nextSleep, generator);
}, ms);
}
// Initialize a generator and get first sleep for the recursive function
var
generator = main(),
firstSleep = generator.next().value;
// Initialize recursive resume function
resume(firstSleep, generator);
这种对睡眠的模仿不同于真正的睡眠函数,因为它不会阻塞线程。它只是JavaScript当前setTimeout函数之上的糖。这种功能类型已经在Task.js中实现,现在应该可以在Firefox中使用。
如果您使用的是Node.js,您可以看看fiber——一种对节点的原生C扩展,一种多线程模拟。
它允许您以阻塞光纤中的执行的方式进行真正的睡眠,但在主线程和其他光纤中是非阻塞的。
下面是他们自己自述文件中的一个例子:
// sleep.js
var Fiber = require('fibers');
function sleep(ms) {
var fiber = Fiber.current;
setTimeout(function() {
fiber.run();
}, ms);
Fiber.yield();
}
Fiber(function() {
console.log('wait... ' + new Date);
sleep(1000);
console.log('ok... ' + new Date);
}).run();
console.log('back in main');
–结果如下:
$ node sleep.js
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
back in main
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)