Zee*_*ang 796 javascript parameters callback settimeout
我有一些JavaScript代码,如下所示:
function statechangedPostQuestion()
{
//alert("statechangedPostQuestion");
if (xmlhttp.readyState==4)
{
var topicId = xmlhttp.responseText;
setTimeout("postinsql(topicId)",4000);
}
}
function postinsql(topicId)
{
//alert(topicId);
}
Run Code Online (Sandbox Code Playgroud)
我得到一个topicId未定义的错误在使用该setTimeout()函数之前,一切正常.
我希望postinsql(topicId)在一段时间后调用我的函数.我该怎么办?
med*_*iev 1083
setTimeout(function() {
postinsql(topicId);
}, 4000)
Run Code Online (Sandbox Code Playgroud)
您需要将匿名函数作为参数而不是字符串提供,后一种方法甚至不应该按照ECMAScript规范工作,但浏览器只是宽松的.这是正确的解决方案,不要依赖于在使用时将字符串作为"函数"传递,setTimeout()或者setInterval()它更慢,因为它必须被评估并且它不正确.
更新:
正如Hobblin在对该问题的评论中所说,现在你可以将参数传递给setTimeout中的函数 Function.prototype.bind()
例:
setTimeout(postinsql.bind(null, topicId), 4000);
Run Code Online (Sandbox Code Playgroud)
Fab*_*hms 694
在现代浏览器中,"setTimeout"接收第三个参数,该参数作为参数发送到计时器末尾的内部函数.
例:
var hello = "Hello World";
setTimeout(alert, 1000, hello);Run Code Online (Sandbox Code Playgroud)
更多细节:
Jir*_*ska 143
在做了一些研究和测试之后,唯一正确的实现是:
setTimeout(yourFunctionReference, 4000, param1, param2, paramN);
Run Code Online (Sandbox Code Playgroud)
setTimeout会将所有额外参数传递给您的函数,以便在那里处理它们.
匿名函数可以用于非常基本的东西,但是在你必须使用"this"的对象的实例中,没有办法让它工作.任何匿名函数都会将"this"更改为指向窗口,因此您将丢失对象引用.
Dav*_*ter 44
这是一个非常古老的问题,已有"正确"的答案,但我想我会提到另一种方法,没有人在这里提到过.这是从优秀的下划线库中复制和粘贴的:
_.delay = function(func, wait) {
var args = slice.call(arguments, 2);
return setTimeout(function(){ return func.apply(null, args); }, wait);
};
Run Code Online (Sandbox Code Playgroud)
您可以将所需的参数传递给setTimeout调用的函数,并作为额外的奖励(通常是奖金),当您调用setTimeout时,传递给函数的参数值将被冻结,因此如果它们更改了值在调用setTimeout()和超时之间的某个时刻,好吧......那不再那么令人沮丧了:)
这是一个小提琴,你可以看到我的意思.
Dav*_*ret 37
我最近遇到了特殊情况需要来使用的setTimeout在循环中.理解这一点可以帮助您了解如何传递参数setTimeout.
方法1
使用forEach和Object.keys根据Sukima的建议:
var testObject = {
prop1: 'test1',
prop2: 'test2',
prop3: 'test3'
};
Object.keys(testObject).forEach(function(propertyName, i) {
setTimeout(function() {
console.log(testObject[propertyName]);
}, i * 1000);
});
Run Code Online (Sandbox Code Playgroud)
我推荐这种方法.
方法2
使用 bind:
var i = 0;
for (var propertyName in testObject) {
setTimeout(function(propertyName) {
console.log(testObject[propertyName]);
}.bind(this, propertyName), i++ * 1000);
}
Run Code Online (Sandbox Code Playgroud)
JSFiddle:http://jsfiddle.net/MsBkW/
方法3
或者,如果您不能使用forEach或bind使用IIFE:
var i = 0;
for (var propertyName in testObject) {
setTimeout((function(propertyName) {
return function() {
console.log(testObject[propertyName]);
};
})(propertyName), i++ * 1000);
}
Run Code Online (Sandbox Code Playgroud)
方法4
但如果你不关心IE <10,那么你可以使用Fabio的建议:
var i = 0;
for (var propertyName in testObject) {
setTimeout(function(propertyName) {
console.log(testObject[propertyName]);
}, i++ * 1000, propertyName);
}
Run Code Online (Sandbox Code Playgroud)
方法5(ES6)
使用块范围变量:
let i = 0;
for (let propertyName in testObject) {
setTimeout(() => console.log(testObject[propertyName]), i++ * 1000);
}
Run Code Online (Sandbox Code Playgroud)
虽然我还是会建议使用Object.keys与forEach在ES6.
dai*_*ain 22
霍布林已就这个问题对此进行了评论,但这应该是一个答案!
使用Function.prototype.bind()是最干净,最灵活的方法(能够设置this上下文的额外好处):
setTimeout(postinsql.bind(null, topicId), 4000);
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请参阅以下MDN链接:
https
://developer.mozilla.org/en/docs/DOM/window.setTimeout#highlighter_547041 https://developer.mozilla.org/en/docs/JavaScript/Reference/Global_Objects/Function /绑定#With_setTimeout
Sch*_*ien 16
一些答案是正确的,但令人费解.
4年后我再次回答这个问题,因为我仍然遇到过于复杂的代码来解决这个问题.有一个优雅的解决方案.
首先,在调用setTimeout时不要传入一个字符串作为第一个参数,因为它有效地调用了对慢速"eval"函数的调用.
那么我们如何将参数传递给超时函数呢?通过使用闭包:
settopic=function(topicid){
setTimeout(function(){
//thanks to closure, topicid is visible here
postinsql(topicid);
},4000);
}
...
if (xhr.readyState==4){
settopic(xhr.responseText);
}
Run Code Online (Sandbox Code Playgroud)
有些人建议在调用超时函数时使用匿名函数:
if (xhr.readyState==4){
setTimeout(function(){
settopic(xhr.responseText);
},4000);
}
Run Code Online (Sandbox Code Playgroud)
语法解决了.但是当调用settopic时,即4秒后,XHR对象可能不一样.因此,预先绑定变量很重要.
小智 15
您可以将参数传递给 setTimeout 回调函数,如下所示:
setTimeout(function, 毫秒, param1, param2, ...)
例如。
function myFunction() {
setTimeout(alertMsg, 3000, "Hello");
}
function alertMsg(message) {
alert(message)
}
Run Code Online (Sandbox Code Playgroud)
Alp*_*til 14
我知道自从提出这个问题以来已经 10 年了,但是,如果您已经滚动到这里,我认为您仍然面临一些问题。Meder Omuraliev 的解决方案是最简单的解决方案,可能对我们大多数人都有帮助,但对于那些不想有任何约束力的人来说,这里是:
setTimeout(function(p){
//p == param1
},3000,param1);
Run Code Online (Sandbox Code Playgroud)
let param1 = 'demon';
setTimeout(function(p){
// p == 'demon'
},2000,(function(){
return param1;
})()
);
Run Code Online (Sandbox Code Playgroud)
function statechangedPostQuestion()
{
//alert("statechangedPostQuestion");
if (xmlhttp.readyState==4)
{
setTimeout(postinsql,4000,(function(){
return xmlhttp.responseText;
})());
}
}
function postinsql(topicId)
{
//alert(topicId);
}
Run Code Online (Sandbox Code Playgroud)
小智 10
我的答案:
setTimeout((function(topicId) {
return function() {
postinsql(topicId);
};
})(topicId), 4000);
Run Code Online (Sandbox Code Playgroud)
说明:
创建的匿名函数返回另一个匿名函数.此函数可以访问最初传递的函数
topicId,因此不会出错.第一个匿名函数立即被调用,传入topicId,因此具有延迟的注册函数可以topicId在调用时通过闭包访问.
要么
这基本上转换为:
setTimeout(function() {
postinsql(topicId); // topicId inside higher scope (passed to returning function)
}, 4000);
Run Code Online (Sandbox Code Playgroud)
编辑:我看到了同样的答案,所以看看他的.但我没有偷他的答案!我只是忘了看.阅读说明,看看它是否有助于理解代码.
更换
setTimeout("postinsql(topicId)", 4000);
Run Code Online (Sandbox Code Playgroud)
同
setTimeout("postinsql(" + topicId + ")", 4000);
Run Code Online (Sandbox Code Playgroud)
或者更好的是,用匿名函数替换字符串表达式
setTimeout(function () { postinsql(topicId); }, 4000);
Run Code Online (Sandbox Code Playgroud)
编辑:
Brownstone的评论不正确,这将按预期工作,如在Firebug控制台中运行它所证明的那样
(function() {
function postinsql(id) {
console.log(id);
}
var topicId = 3
window.setTimeout("postinsql(" + topicId + ")",4000); // outputs 3 after 4 seconds
})();
Run Code Online (Sandbox Code Playgroud)
请注意,我同意其他人应避免传递字符串,setTimeout因为这会调用eval()字符串而不是传递函数.
支持setTimeout中参数的最简单的跨浏览器解决方案:
setTimeout(function() {
postinsql(topicId);
}, 4000)
Run Code Online (Sandbox Code Playgroud)
如果您不介意不支持IE 9及更低版本:
setTimeout(postinsql, 4000, topicId);
Run Code Online (Sandbox Code Playgroud)


https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout
| 归档时间: |
|
| 查看次数: |
539436 次 |
| 最近记录: |