填充解决方案
这里是一些JavaScript代码,我从以前的项目中进行了更新,现在已经扩展了触发和更新方法。它与Jan Wikholm的解决方案相似(+1),但更加完整,考虑到清除、传递参数以及必要时防止eval
:
(function(keep){
keep.setTimeout = window.setTimeout;
keep.clearTimeout = window.clearTimeout;
keep.TO = function(){};
keep.list = {};
keep.settings = {
eval: false
};
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;
}
};
keep.makeFunction = function(data){
return function(args){
args = data.args.slice();
if ( keep.settings.eval ) {
args[0] = data.param;
args[1] = 0;
keep.setTimeout.apply( window, args );
}
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.');
}
window.clearTimeout( data.tid );
};
};
window.setTimeout = function( param, timeout ){
if ( keep.checkParam( param ) ) {
var tid, data;
if ( param instanceof keep.TO ) {
data = param;
data.args[1] = data.timeout;
}
else {
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;
tid = new Number(data.tid);
tid.clear = window.clearTimeout;
tid.trigger = window.triggerTimeout;
tid.update = window.updateTimeout;
return tid;
}
};
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);
}
};
window.getTimeout = function( tid ){
var obj;
if ( (obj = keep.list[tid]) ) {
return obj;
}
};
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);
}
};
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);
}
};
window.clearAllTimeouts = function(){
for ( var i in keep.list ) {
window.clearTimeout(i);
};
};
window.onunload = (function(previous){
return function(){
window.clearAllTimeouts();
keep.list = {};
previous && previous.call(window);
};
}(window.onunload));
})({});
包含
只需将上述内容放在一个js文件中,并使用普通的脚本标签将其包含到您的页面中,代码不需要以任何方式调用:
<script src="timeouts.js"></script>
用法
显然,这应该像普通的setTimeout
调用一样使用,但现在您有了额外的方法,应该能够提供更多的灵活性。
var tid = setTimeout( function(){ alert('OK Computer') }, 2000 );
例如,您可以取消原始操作并强制提前触发超时:
setTimeout( function(){ triggerTimeout( tid ); }, 500 );
或者,您可以更新超时时间 (确保我们记住新返回的tid):
setTimeout( function(){ tid = updateTimeout( tid, 5000 ); }, 500 );
您也可以进行常规操作:
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。
禁用eval的好处在于代码将使用常规函数调用来触发超时,即.apply()
。这意味着无论您使用哪种浏览器,都可以通过setTimeout向超时函数传递参数-这通常不是跨浏览器可靠的功能。例如:
setTimeout( function(a){ alert(a) }, 2000, 'Hello World' );