有没有比下面的pausecomp函数(取自此处)更好的方法来设计JavaScript中的睡眠?
function pausecomp(millis)
{
var date = new Date();
var curDate = null;
do { curDate = new Date(); }
while(curDate-date < millis);
}
这不是JavaScript中的Sleep的重复-动作之间的延迟;我希望在函数的中间有一个真正的睡眠,而不是在代码执行之前有一段延迟。
这可以使用Java的睡眠方法来完成。我已经在Firefox和Internet Explorer中测试过它,它不会锁定计算机,不会占用资源,也不会导致无休止的服务器攻击。对我来说,这似乎是一个干净的解决方案。
首先,您必须在页面上加载Java并使其方法可用。为了做到这一点,我这样做了:
<html>
<head>
<script type="text/javascript">
function load() {
var appletRef = document.getElementById("app");
window.java = appletRef.Packages.java;
} // endfunction
</script>
<body onLoad="load()">
<embed id="app" code="java.applet.Applet" type="application/x-java-applet" MAYSCRIPT="true" width="0" height="0" />
然后,当您想要在JavaScript代码中轻松暂停时,您需要做的就是:
java.lang.Thread.sleep(xxx)
其中xxx是以毫秒为单位的时间。在我的案例中(作为理由),这是一家非常小的公司后端订单履行的一部分,我需要打印一张必须从服务器加载的发票。我是通过将发票(作为网页)加载到iFrame中,然后打印iFrame来完成的。
当然,我必须等到页面完全加载后才能打印,所以JavaScript代码必须暂停。我通过让发票页面(在iFrame中)使用onLoad事件更改父页面上的隐藏表单字段来实现这一点。打印发票的父页面上的代码如下(为清晰起见,将不相关的部分切割):
var isReady = eval('document.batchForm.ready');
isReady.value = 0;
frames['rpc_frame'].location.href = url;
while (isReady.value == 0) {
java.lang.Thread.sleep(250);
} // endwhile
window.frames['rpc_frame'].focus();
window.frames['rpc_frame'].print();
因此,用户按下按钮,脚本加载发票页面,等待,每季度检查一次发票页面是否完成加载,并弹出打印对话框,供用户将其发送到打印机。QED。
我相信有一百万种方法可以做得更好,但我想我可以通过创建一个对象来尝试一下:
// execute code consecutively with delays (blocking/non-blocking internally)
function timed_functions()
{
this.myfuncs = [];
this.myfuncs_delays = []; // mirrors keys of myfuncs -- values stored are custom delays, or -1 for use default
this.myfuncs_count = 0; // increment by 1 whenever we add a function
this.myfuncs_prev = -1; // previous index in array
this.myfuncs_cur = 0; // current index in array
this.myfuncs_next = 0; // next index in array
this.delay_cur = 0; // current delay in ms
this.delay_default = 0; // default delay in ms
this.loop = false; // will this object continue to execute when at end of myfuncs array?
this.finished = false; // are we there yet?
this.blocking = true; // wait till code completes before firing timer?
this.destroy = false; // <advanced> destroy self when finished
this.next_cycle = function() {
var that = this;
var mytimer = this.delay_default;
if(this.myfuncs_cur > -1)
if(this.myfuncs_delays[this.myfuncs_cur] > -1)
mytimer = this.myfuncs_delays[this.myfuncs_cur];
console.log("fnc:" + this.myfuncs_cur);
console.log("timer:" + mytimer);
console.log("custom delay:" + this.myfuncs_delays[this.myfuncs_cur]);
setTimeout(function() {
// Time is up! Next cycle...
that.cycle();
}, mytimer);
}
this.cycle = function() {
// Now check how far we are along our queue.. is this the last function?
if(this.myfuncs_next + 1 > this.myfuncs_count)
{
if(this.loop)
{
console.log('looping..');
this.myfuncs_next = 0;
}
else
this.finished = true;
}
// First check if object isn't finished
if(this.finished)
return false;
// HANDLE NON BLOCKING //
if(this.blocking != true) // Blocking disabled
{
console.log("NOT BLOCKING");
this.next_cycle();
}
// Set prev = current, and current to next, and next to new next
this.myfuncs_prev = this.myfuncs_cur;
this.myfuncs_cur = this.myfuncs_next;
this.myfuncs_next++;
// Execute current slot
this.myfuncs[this.myfuncs_cur]();
// HANDLE BLOCKING
if(this.blocking == true) // Blocking enabled
{
console.log("BLOCKING");
this.next_cycle();
}
return true;
};
// Adders
this.add = {
that:this,
fnc: function(aFunction) {
// Add to the function array
var cur_key = this.that.myfuncs_count++;
this.that.myfuncs[cur_key] = aFunction;
// Add to the delay reference array
this.that.myfuncs_delays[cur_key] = -1;
}
}; // end::this.add
// setters
this.set = {
that:this,
delay: function(ms) {
var cur_key = this.that.myfuncs_count - 1;
// This will handle the custom delay array this.that.myfunc_delays
// Add a custom delay to your function container
console.log("setting custom delay. key: "+ cur_key + " msecs: " + ms);
if(cur_key > -1)
{
this.that.myfuncs_delays[cur_key] = ms;
}
// So now we create an entry on the delay variable
},
delay_cur: function(ms) { this.that.delay_cur = ms; },
delay_default: function(ms) { this.that.delay_default = ms; },
loop_on: function() { this.that.loop = true; },
loop_off: function() { this.that.loop = false; },
blocking_on: function() { this.that.blocking = true; },
blocking_off: function() { this.that.blocking = false; },
finished: function(aBool) { this.that.finished = true; }
}; // end::this.set
// Setters
this.get = {
that:this,
delay_default: function() { return this.that.delay_default; },
delay_cur: function() { return this.that.delay_cur; }
}; // end::this.get
} // end:::function timed_functions()
使用方式如下:
// // // BEGIN :: TEST // // //
// Initialize
var fncTimer = new timed_functions;
// Set some defaults
fncTimer.set.delay_default(1000);
fncTimer.set.blocking_on();
// fncTimer.set.loop_on();
// fncTimer.set.loop_off();
// BEGIN :: ADD FUNCTIONS (they will fire off in order)
fncTimer.add.fnc(function() {
console.log('plan a (2 secs)');
});
fncTimer.set.delay(2000); // Set a custom delay for previously added function
fncTimer.add.fnc(function() {
console.log('hello world (delay 3 seconds)');
});
fncTimer.set.delay(3000);
fncTimer.add.fnc(function() {
console.log('wait 4 seconds...');
});
fncTimer.set.delay(4000);
fncTimer.add.fnc(function() {
console.log('wait 2 seconds');
});
fncTimer.set.delay(2000);
fncTimer.add.fnc(function() {
console.log('finished.');
});
// END :: ADD FUNCTIONS
// NOW RUN
fncTimer.cycle(); // Begin execution
// // // END :: TEST // // //