【问题标题】:Variable scope with deferred / ajax in jQueryjQuery中具有延迟/ ajax的变量范围
【发布时间】:2013-07-17 07:09:29
【问题描述】:

我认为我使用的是非常标准的设置。单击元素以调用处理 ajax 请求的函数。

在使用异步任何东西并试图弄清楚jQuery deferreds 时,我对变量范围和回调的有限理解让我微弱的大脑受伤。

$('<div>')
.on({
    click : function(){
        console.log(
            fetchMyData() // this will be 'undefined' but why?
        )
    }
})

function fetchMyData(){
    $.ajax({
        // ajax setup
    })
    .done(function(response){
        console.log( response ); // shows 'hello' as expected
        return response; 
    })
}

我知道 ajax 调用不一定会在我执行 console.log() 时完成,因为它当然是异步的。

那么我怎样才能让fetchMyData() 准备好后显示 ajax 结果?

【问题讨论】:

  • 你想做什么? fetchMyData() 记录为 undefined 因为它不返回任何内容。你有什么理由避免.done()
  • 返回 done 回调中的任何内容实际上什么都不做。您可以在 fetchMyData 函数中使用 return $.ajax({...。然后在您的点击处理程序中,使用 fetchMyData.done(function() { console.log("foo"); });
  • 将显示结果的代码放在您的 return 语句当前所在的位置...

标签: javascript jquery jquery-deferred jqxhr


【解决方案1】:

您应该更改 fetchMyData 函数的作用。尝试返回承诺对象。

$('<div>').click(function()
{

    var fetchMyDataPromise  = fetchMyData() ;

    fetchMyDataPromise.done(function(response)
    {
        console.log(response);
    });

});

function fetchMyData()
{
    return  $.ajax({ // ajax setup });
}  

【讨论】:

    【解决方案2】:

    你可以在这样的时候使用 jQuery:

    $('<div>')
        .on({
            click : function() {
    
               $.when(fetchMyData()).then(function(data) {
                        console.log(data);
               });
             }
        });
    
        function fetchMyData(){
            return $.ajax({
                // ajax setup
            });
        }
    

    【讨论】:

    • 这很有趣。但现在我必须在点击处理程序中进行设置。必须有一种模拟同步行为的方法,所以我可以写console.log( fetchMyData() );
    【解决方案3】:

    那么我怎样才能让 fetchMyData() 准备好后显示 ajax 结果呢?

    您已经在 .done 回调中完成了该操作。如果您希望fetchMyData返回响应,则必须使用同步调用,这通常不是正确的做法(因为 UI 将冻结直到响应到达)。


    也许你想修改你的函数来接受回调:

    function fetchMyData(thenDoThis){
        $.ajax({
            // ajax setup
        }).done(thenDoThis)
    }
    
    function doSomethingWithResponse(response) {
        // do something
    }
    

    然后这样称呼它:

    fetchMyData(doSomethingWithResponse);
    

    或者像这样:

    $('<div>').click(function() {
        fetchMyData(function(response){
            console.log(response);
        });
    });
    

    【讨论】:

    • 谢谢。这就是我所想的。有什么方法可以避免回调?因为对我来说,这感觉就像是过于复杂的代码。 @L105 正在谈论 .when(),这听起来很有趣
    • 其他建议(由 L105 和 Tomas Santos 提出)都暗示您传递了一个要在响应到达时调用的函数,因此它们只是回调的不同语法(依赖于承诺,这​​确实是很有意思)。这并不过分复杂,它是处理异步操作的标准方法。避免它的唯一方法是使用同步请求,正如我所提到的那样,这并不好......
    • 是的,我已经与那场战斗战斗了很长时间,使用async:false 并最终接受它只是自找麻烦。我不推荐使用同步 AJAX,也就是 SJAX
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-02
    • 1970-01-01
    • 1970-01-01
    • 2013-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多