【问题标题】:Javascript closure function doesn't return the right valueJavascript 闭包函数不返回正确的值
【发布时间】:2013-01-16 03:20:27
【问题描述】:

我的 Javascript 代码有问题,不知道为什么它不能运行。

这是我的计时器:

var time = 0;
startTimer();

function startTimer(){
    setInterval(function(){
    time=time+1;
    },10);
}

这里的代码有效(我在单击按钮时运行 timeoutTester(),然后它会发出警报并向我显示时差):

function timeoutTester(){
    var snap_time1 = time;
    setTimeout(function(){
        var snap_time2 = time;
        var diff = snap_time2-snap_time1;
        alert(diff);            //works: ~100 everytime...
    },1000);
}

但是这里的代码不起作用(我通过单击按钮运行 testTimer()):

function timeoutTester(){
    var snap_time1 = time;
    var result;
    setTimeout(function(){
        var snap_time2 = time;
        result = snap_time2-snap_time1;
    },1000);
    alert(result); //doesn't work! It always shows me: "undefined"
    return result;
}

function testTimer(){
    var counter = 0;
    setInterval(function(){
        counter = counter + 1;
        alert(counter);         //works: 1,2,3,....
        var result = timeoutTester();
        alert(result);  //doesn't work! It always shows me: "undefined"
    }, 3000);
}

您知道问题可能出在哪里吗? (在浏览器中调试时没有错误!)

更新

我了解到警报(结果);立即执行,而 result 还没有值。

但是由于我是从外部调用 timeoutTester(),我仍然需要这个函数的返回值!

有什么想法吗?

【问题讨论】:

  • 这一定是今年被问到最多的问题。在 Stack Overflow 中查找“异步变量 javascript”,看看是否找到了什么。
  • @elclanrs:谢谢你的提示,但我现在仍然知道如何解决这个问题......所以我稍微改变了这个问题。

标签: javascript closures return-value settimeout alert


【解决方案1】:

在您的最后一个示例(不起作用的示例)中,调用setTimeout(function()...) 不会立即执行该函数,但会立即返回。当它返回时,result 仍然未定义,因为该函数尚未执行。

出于同样的原因,前面的示例(在 timeout 函数中调用 alert())之所以有效,是因为对 alert() 的调用发生在 result 被赋值之后。

如果出于某种原因您不想直接从 timeout 函数中调用 alert(),您可以将最后一个示例重写为:

function timeoutTester(){
    var snap_time1 = time;
    setTimeout(function(){
        var snap_time2 = time;
        alertResult(snap_time2-snap_time1);
    },1000);
}
function alertResult(result) {
    alert(result);
}

(顺便说一下,startTimer(1000000000000); 的调用看起来很吓人,直到我意识到这个参数被忽略了。:-)。)

【讨论】:

  • 但是是否可以从外部调用函数并获得返回值?
【解决方案2】:

要完成此操作,您需要使用全局:

var timeoutTesterResult;

function timeoutTester(){
    var snap_time1 = time;
    var result;
    setTimeout(function(){
        var snap_time2 = time;
        timeoutTesterResult = snap_time2-snap_time1;
        alert(timeoutTesterResult);                    //works: ~100
    },1000);
}

只有在设置/更改后才获得这个全局的第二个超时:

function testTimer(){
    var counter = 0;
    setInterval(function(){
        counter = counter + 1;
        alert(counter);         //works: 1,2,3,....
        timeoutTester();
        setTimeout("alert(timeoutTesterResult)",1000); //works: ~100
    }, 3000);
}

这就是“通过全局”解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多