确定Javascript函数范围问题

Net*_*ool 2 javascript jquery scope function

很明显我不明白函数是如何在Javascript中作用域的.这是最新的例子:

function riseData() { 
    var jsonResult;
    $.ajax({
        success: function(data, textStatus, jqXHR){
            jsonResult = jqXHR.responseText;
            alert("Inside: " + jsonResult);
        },          
        error: function (jqXHR, textStatus, errorThrown) {  
            $('#errLog').append('<br>Status: ' + qXHR.statusText);                  
        }
    });
    return jsonResult;
}

$(document).ready(function(){
    var intervalID = setInterval('UTCclock()',100); 
    alert("Outside: " + riseData());                            
});
Run Code Online (Sandbox Code Playgroud)

当我执行此操作时,"Inside"警报功能正常,但"Outside"警报显示"undefined",即使roseData()显然只是提前几行定义.代码中前面有一个$ .ajaxSetup,它定义了ajax调用的参数.ajax调用成功返回"Inside"警报中的请求数据.

我只是没有丝毫的线索如何使必要的数据(jqXHR.responseText)可用于脚本的其他部分.

任何人都可以指点我的"Javascript范围傻瓜"方法解决这个问题?

ick*_*fay 5

你的例子范围很好.您的问题是您不了解JavaScript主要是异步的含义.

让我通过你的例子向你展示.

  1. 您的文档就绪处理程序运行
  2. 它叫riseData.
  3. riseData声明一个变量jsonResult.
  4. riseData调用$.ajax,调度AJAX请求,但响应将在稍后发生.
  5. 由于$.ajax通常是非阻塞/异步,因此riseData继续并返回jsonResult.由于jsonResultAJAX请求尚未完成尚未分配,undefined因此返回默认值.
  6. 在文档就绪处理程序中,您最终会得到alert("Outside: "+undefined);.

事件循环到几毫秒之后,会发生这种情况:

  1. AJAX请求已完成.jQuery将此转发给您的回调.
  2. jsonResult已设置,但riseData已经返回.
  3. alert内部riseData与新的数据警报,之后文档准备好处理程序已经惊动undefined.

这个问题有两种解决方案.第一种解决方案很简单,但往往会导致更糟糕的用户体验.此解决方案是添加async: false选项$.ajax.这会$.ajax阻止并冻结浏览器.

第二种解决方案是对几乎所有东西采用异步风格.这意味着riseData接受一个回调并在AJAX响应处理程序中调用它.这是使用此方法转换的代码:

function riseData(callback) { 
    $.ajax({
        success: function(data, textStatus, jqXHR){
            var jsonResult = jqXHR.responseText;
            alert("Inside: " + jsonResult);
            callback(jsonResult);
        },          
        error: function (jqXHR, textStatus, errorThrown) {  
            $('#errLog').append('<br>Status: ' + qXHR.statusText);                  
        }
    });
}

$(document).ready(function(){
    //var intervalID = setInterval('UTCclock()',100); 
    // Unrelated, but it's better to pass a
    // function into setInterval than a string.
    var intervalID = setInterval(UTCclock, 100);
    riseData(function(jsonResult) {
        alert("Outside: " + jsonResult);
    });
});
Run Code Online (Sandbox Code Playgroud)