JavaScript的setTimeout函数无法识别函数参数

4
我正在编写一个Google Chrome扩展程序。我使用setTimeout来减慢向服务器发送请求的速度。但是,setTimeout并没有按预期工作。它返回一个错误,说reqUrl未定义。
根据stackoverflow上类似问题的答案,这似乎是一个超出范围的问题,除了将reqUrl变成全局变量之外,我不知道如何解决它,但这似乎不是一个很好的解决方案。如果我删除括号,它就会失控,根本没有时间延迟。
如何让它正常工作?
以下是代码。尽管我认为slowdow函数不是问题的核心,但我还是包含了它。
openDetailPg(profileLink[currentLink]); 
function openDetailPg(reqUrl)
{
    console.log('openDetailPg at '+reqUrl);
    setTimeout("createDetailWindow(reqUrl)",slowDown());
    ++sendCount;
    timeOfLastRequest=new Date().getTime();
};
function createDetailWindow(detailUrl)
{
    console.log('createDetailWindow');
    chrome.tabs.create({windowId: mainWindowId, url: detailUrl}, 
    function (tab)
    {
        console.log('    OpenDetailPg Created Tab '+tab.id+' with slow down of '+slowDown().toFixed(0));
        chrome.tabs.executeScript(tab.id, {file: 'profile.js'});
    })
};
function slowDown()
{
    //console.log('  Slowdown: last interval '+ (new Date().getTime()-timeOfLastRequest)+' milisec.')
    if (new Date().getTime()-timeOfLastRequest>minDelay)
    {
        console.log('  Previous Delay Greater Than Minimum Delay, Resetting Speed Count');
        sendCount=1; 
        timeOfFirstRequest=new Date().getTime(); //else forget about it, reset time of first request
    }
    elapsedTime=new Date().getTime()-timeOfFirstRequest;
    avgSpeed = elapsedTime/sendCount;
    //console.log("  Started @ "+timeOfFirstRequest+" Current time "+new Date().getTime()+" Avg time fr 1st HTTPRequest "+avgSpeed.toFixed(0)+' milisec over '+sendCount+' Req');
    if (avgSpeed<minDelay)
    {
        //console.log("  Delaying request by "+((minDelay-avgSpeed).toFixed(0))+" milisecs");
        return minDelay-avgSpeed;
    }
    else
    {
        //console.log('  No Delay on Request');
        return 1;
    }
};

2
未来建议:下次请提供最少量的代码以帮助你解决问题。你贴了太多的代码。许多愿意帮助你的人可能会因为这些过多的代码而放弃(包括那些被注释掉的日志调用)。 - Robert Koritnik
6个回答

4

setTimeout({函数名}, {延迟时间}, {参数1}, {参数2}...)

示例:

setTimeout(callMe, 1000, 'say','hello');
function callMe(p1, p2){
alert(p1+" "+p2); //alerts say hello
}

3
function openDetailPg(reqUrl)
{
    console.log('openDetailPg at '+reqUrl);
    setTimeout(function(){createDetailWindow(reqUrl)},slowDown());
    ++sendCount;
    timeOfLastRequest=new Date().getTime();
};

3
您需要使用匿名函数来实现,例如:
setTimeout(function(){createDetailWindow(reqUrl)},slowDown());

这个很好地解决了问题。谢谢。但是为什么在这里需要使用匿名函数呢?我知道它解决了作用域问题,但我不明白为什么。 - jeromekjerome
有几种方法可以做到这一点。 setTimeout 函数在第一个参数中需要函数或字符串的处理程序。如果传递字符串,则它的工作方式与 eval 函数完全相同,但是由于闭包,传递该字符串的变量未定义。当您传递简单的处理程序时,setTimeout 调用该处理程序。当您传递匿名函数时,setTimeout 认为您传递了处理程序。使用闭包,如果之前声明过,您可以在匿名函数中看到变量。但是总的来说,您可以将任何内容传递给匿名函数: function(){var test=test2+test3;for(var i=0;i<5;i++)...} 一切 :) - antyrat

2

尝试以下方法:

setTimeout(function() { createDetailWindow(reqUrl); }, slowDown()); 

2

试试这个:

setTimeout(function(){ createDetailWindow(reqUrl) },slowDown());

0

你正在执行的 JavaScript 代码看起来像这样:createDetailWindow(reqUrl),但实际上这不是你想要的——你试图传递最初传递给 openDetailPg 的字符串,对吧?因此,你传递给 setTimeout 的字符串需要适当地构造:"createDetailWindow('" + reqUrl + "')"(假设 reqUrl 总是被正确转义)。

顺便说一下,最好将东西压缩成一个 sscce,我花了一段时间才找到调用 setTimeout 的位置。


1
(其他使用闭包的答案比我的干净得多得多。) - Dave Newton
1
将字符串传递给 setTimeout 已经是过时的功能。 - Robert Koritnik
因此,我跟进了一下。然而,我的评论实际上解释了为什么OP会看到这个错误。 - Dave Newton
这个会崩溃:setTimeout("createDetailWindow(reqUrl)",slowDown()); 但这个没有延迟地运行:setTimeout(createDetailWindow(reqUrl),slowDown()); - jeromekjerome
1
因为在第二个例子中,您正在执行createDetailWindow并将其结果返回给setTimeout。 setTimeout期望一个函数参数(或字符串,但正如指出的那样,不好)。这就是为什么所有示例都传递一个包括reqUrl参数的匿名函数的原因。 - Dave Newton
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接