Javascript 尽早执行settimeout
我在使用settimeout执行超时后的事件。我遇到的问题是,其他javascript事件期望这些事件同步发生。因为它们现在是在超时后执行的,所以我希望能够通过其他javascript事件提前触发它们(这样需要它们的事件就不会失败) 不管是谁,如果我这样做:Javascript 尽早执行settimeout,javascript,jquery,settimeout,Javascript,Jquery,Settimeout,我在使用settimeout执行超时后的事件。我遇到的问题是,其他javascript事件期望这些事件同步发生。因为它们现在是在超时后执行的,所以我希望能够通过其他javascript事件提前触发它们(这样需要它们的事件就不会失败) 不管是谁,如果我这样做: timeout = setTimeout(function() { alert('hi'); }, 10000); ,我希望在10秒之前发生,我怎么能做到 如果需要,解决方案可以涉及jquery。谢谢 编辑: 仅通过访问超时对象就可以做到
timeout = setTimeout(function() { alert('hi'); }, 10000);
,我希望在10秒之前发生,我怎么能做到
如果需要,解决方案可以涉及jquery。谢谢
编辑:
仅通过访问超时对象就可以做到这一点吗?使用
clearTimeout
并重新安排一个较早的时间。因此,如果您做出任何延迟其自身功能的动作:
function sayHi() {
alert('hi');
}
您可以使用超时和常规函数调用:
var timeout = setTimeout(sayHi, 10000); // say hi after 10 seconds
或者,要在超时过期之前调用它,只需在需要时调用该函数:
sayHi();
我走对了吗?如果需要取消超时,请在timeout
变量上调用cleartimout()
if (timeout)
clearTimeout(timeout);
只需将函数输出并给它命名:
function handler(){
alert('hi');
}
timeout = setTimeout(handler, 10000);
然后您可以在其他地方使用
handler()调用它代码>您无法使用标准的设置超时来跟踪它,但Javascript允许您根据需要增强功能
例如,您可以拥有自己的增强型setTimeout
:
var _setTimeout = window.setTimeout;
var timeouts = [];
window.setTimeout = function(fn, ms) {
var id = _setTimeout(fn, ms);
timeouts[id] = fn;
return id;
};
window.premature = function(id) {
var fn = timeouts[id];
if (fn) {
clearTimeout(id);
if (fn instanceof String) {
eval(fn);
} else {
fn()
}
}
};
function printDate(str) {
$("body").append("<p>" + str + ". " + new Date() + "</p>");
}
$(function() {
var id1 = setTimeout(function() { printDate("id1"); }, 10000);
var id2 = setTimeout(function() { printDate("id2"); }, 10000);
printDate("first one");
// just to demonstrate that the string version works too
setTimeout("window.premature(" + id1 +")", 5000);
});
var\u setTimeout=window.setTimeout;
var超时=[];
window.setTimeout=函数(fn,毫秒){
变量id=_设置超时(fn,ms);
超时[id]=fn;
返回id;
};
window.premature=函数(id){
var fn=超时[id];
如果(fn){
清除超时(id);
if(字符串的fn实例){
eval(fn);
}否则{
fn()
}
}
};
函数printDate(str){
$(“正文”)。追加(“”+str+”+newdate()+“”);
}
$(函数(){
var id1=setTimeout(函数(){printDate(“id1”);},10000);
var id2=setTimeout(函数(){printDate(“id2”);},10000);
打印日期(“第一次”);
//只是为了证明字符串版本也可以工作
setTimeout(“window.premature(+id1+”),5000);
});
你可以看到它在
请注意,这个简单的黑客攻击并不考虑在超时发生时清除已使用的ID,但它只是为了表明,如果您真的需要,您可以在Javascript中执行此类操作。polyfill解决方案
这里是我从以前的项目中更新的一些javascript,现在使用触发器和更新方法对其进行了扩展;它与Jan Wikholm的解决方案(+1)类似,但考虑到清除、参数传递和防止eval
(如果需要):
(function(keep){
/// a few things to remember
keep.setTimeout = window.setTimeout;
keep.clearTimeout = window.clearTimeout;
keep.TO = function(){};
keep.list = {};
keep.settings = {
eval: false /// set this to true if you wish to support string timeouts
};
/**
* Quick check function to prevent eval
*/
keep.checkParam = function( param ){
if ( !keep.settings.eval && typeof param == 'string' ) {
throw new Error('setTimeout blocked evaluation of string, ' +
'use a function instead.');
return false;
}
else if ( param ) {
return true;
}
};
/**
* Simple function constructor to avoid trapping unwanted references
*/
keep.makeFunction = function(data){
return function(args){
/// copy our args array
args = data.args.slice();
/// do we allow eval?
if ( keep.settings.eval ) {
/// if so, reuse setTimeout for it's abilities
args[0] = data.param; /// use the original param
args[1] = 0; /// trigger immediately
keep.setTimeout.apply( window, args );
}
// more secure, assume dealing with function -- not string
else if ( keep.checkParam( data.param ) && data.param.apply ) {
data.param.apply( window, args.slice(2) );
}
else {
throw new Error('unsupported param for setTimeout' +
' i.e. non-function used.');
}
/// clear our storage of this tid
window.clearTimeout( data.tid );
};
};
/**
* Sets timeouts just like you would expect
*/
window.setTimeout = function( param, timeout ){
if ( keep.checkParam( param ) ) {
var tid, data;
/// support passing a timeout object as param
if ( param instanceof keep.TO ) {
data = param;
data.args[1] = data.timeout;
}
else {
/// create an object to store the timeout info
data = new keep.TO();
data.func = keep.makeFunction(data);
data.param = param;
data.timeout = timeout;
data.args = Array.prototype.slice.call(arguments,0);
data.args[0] = data.func;
}
data.tid = keep.setTimeout.apply( window, data.args );
keep.list[data.tid] = data;
/// enhance the returned number to support .clear, .trigger and .update
tid = new Number(data.tid);
tid.clear = window.clearTimeout;
tid.trigger = window.triggerTimeout;
tid.update = window.updateTimeout;
return tid;
}
};
/**
* Clearing timeouts since 2013
*/
window.clearTimeout = function( tid ){
if ( this instanceof Number ) {
tid = 0 + this;
}
var obj;
if ( (obj = window.getTimeout(tid)) ) {
delete keep.list[tid];
keep.clearTimeout.call(window, tid);
}
};
/**
* Returns the internal timeout storage object
*/
window.getTimeout = function( tid ){
var obj;
if ( (obj = keep.list[tid]) ) {
return obj;
}
};
/**
* Clears and fires a timeout before it's outed time
*/
window.triggerTimeout = function( tid ){
if ( this instanceof Number ) {
tid = 0 + this;
}
var obj;
if ( (obj = window.getTimeout(tid)) ) {
window.clearTimeout(tid);
obj.func.call(window);
}
else {
throw new Error('No Timeout found to trigger for ID '+ tid);
}
};
/**
* Clears and recreates an existing timeout, returns a new timeout id.
*/
window.updateTimeout = function( tid, timeout ){
if ( this instanceof Number ) {
if ( arguments.length == 1 ) {
timeout = tid;
}
tid = 0 + this;
}
var obj;
if ( (obj = window.getTimeout(tid)) ) {
obj.timeout = timeout;
window.clearTimeout(tid);
return window.setTimeout(obj);
}
else {
throw new Error('No Timeout found to update for ID ' + tid);
}
};
/**
* Utility function to tidy up
*/
window.clearAllTimeouts = function(){
for ( var i in keep.list ) {
window.clearTimeout(i);
};
};
/// Tidy up
window.onunload = (function(previous){
return function(){
window.clearAllTimeouts();
keep.list = {};
previous && previous.call(window);
};
}(window.onunload));
})({});
包括
只需将上述内容放在js文件中,并使用普通脚本标记将其包含到页面中,就不需要以任何方式调用代码:
<script src="timeouts.js"></script>
例如,您可以取消原始设置并强制提前触发超时:
setTimeout( function(){ triggerTimeout( tid ); }, 500 );
或者,您可以更新超时(确保我们记住新返回的tid):
您还可以执行通常的操作:
setTimeout( function(){ clearTimeout( tid ); }, 1000 );
这些方法中的每一种都可以通过tid
本身访问:
setTimeout( function(){ tid.trigger(); }, 1000 );
setTimeout( function(){ tid.update( 5000 ); }, 1000 );
setTimeout( function(){ tid.clear(); }, 1000 );
默认情况下,此代码阻止将setTimeout
与字符串参数一起使用,主要是因为传递函数比传递字符串要好得多。要更改此设置,可以将以下设置切换为true:
keep.settings = {
eval: true
};
但是,不建议这样做
禁用eval还有一个额外的好处,即代码将使用普通函数调用来触发超时,即.apply()
。这意味着无论您使用什么浏览器,都可以通过setTimeout将参数传递给timeout函数,这通常不是跨浏览器可以依赖的。e、 g:
setTimeout( function(a){ alert(a) }, 2000, 'Hello World' );
“其他javascript事件期望这些事件同步发生”。。。这听起来像是一个有问题的设计对不起,我不清楚。我很好奇是否可以只使用setTimeout的返回值。@GoldenNewby:setTimeout()
的返回值只是一个ID,您可以跟踪它(并取消它)。否则就没什么用了。@Cory+1但我不同意否则就没什么用了。如果你有一个注册的ID,我认为你可以有一个triggerTimeout
,getTimeout
或者甚至updateTimeout
方法以及set和clear,但遗憾的是它们并不存在,但是它们可以写为polyfill include,带有setTimeout
和cleartimout
的定制覆盖。太棒了,这正是我想要了解的信息,太棒了,我不需要亲自编写它。谢谢:dtrealsetTimeout
接受两个以上的参数,毫秒参数之后的任何参数都会传递到回调。示例:setTimeout(警报,2000,“两秒钟后将传递给警报”)代码>
keep.settings = {
eval: true
};
setTimeout( function(a){ alert(a) }, 2000, 'Hello World' );