2011-11-08 96 views
11

我有一個必須多次調用服務器的web應用程序。到目前爲止,我有一個長嵌套的回調鏈;但我想用jQuery的when,then等功能。但是,我似乎無法使用then之後再次運行。使用jQuery推遲鏈接ajax請求

$ 
.when ($.get('pages/run-tool.html')) 
.then (function (args) 
{ 
    // This works fine 
    alert(args); 
    $('#content').replaceWith (args); 
    $('#progress-bar').progressbar ({value: 0}); 
}) 
.then ($.get('pages/test.html')) 
.done (function(args) 
{ 
    // This prints the same as the last call 
    alert (args); 
}); 

我在做什麼錯?我想它的一些範圍問題,因爲我可以看到正在執行的第二個get調用。使用兩個不同的args變量不會有幫助,因爲傳遞給done函數的參數仍然是第一個請求get

回答

29

作爲更新:

隨着現代的jQuery(1.8+)你不需要初步因爲得到返回遞延承諾。

另外,管道已棄用。改爲使用,然後使用。請務必返回新獲得的結果,該結果將成爲後續然後/*完成*/失敗調用所附的承諾。

所以:

$.get('pages/run-tool.html') 
.then (function (args) { // this will run if the above .get succeeds 
    // This works fine 
    alert(args); 
    $('#content').replaceWith (args); 
    $('#progress-bar').progressbar ({value: 0}); 
}) 
.then (function() { // this will run after the above then-handler (assuming it ran) 
    return $.get('pages/test.html'); // the return value creates a new Deferred object 
}) 
.done (function(args) { // this will run after the second .get succeeds (assuming it ran) 
    alert (args); 
}); 
12

所有三個回調(兩個與then和一個與done)適用於相同的請求 - 原始when調用。這是因爲then返回的是相同的Deferred對象,而不是新的對象,因此您可以添加多個事件處理程序。

您需要改用pipe

$ 
.when ($.get('pages/run-tool.html')) 
.then (function (args) 
{ 
    // This works fine 
    alert(args); 
    $('#content').replaceWith (args); 
    $('#progress-bar').progressbar ({value: 0}); 
}) 
.pipe (function() { 
    return $.get('pages/test.html'); // the return value creates a new Deferred object 
}) 
.done (function(args) 
{ 
    alert (args); 
}); 
+0

謝謝,這工作!我會立即接受,只要stackoverflow允許我:) – Anteru

+0

jQuery鏈接仍然看起來很可怕 – PHearst

+1

@PHearst請注意,此方法現在已被棄用。 – lonesomeday

-2

我的方法是應用回調函數:

A(function(){ 
     B(function(){ 
      C()})}); 

其中A,B可以寫成

function A(callback) 
$.ajax{ 
    ... 
    success: function(result){ 
     ... 
     if (callback) callback(); 
    } 
} 
+3

然而,這並不使用jQuery的延遲,它很容易產生「金字塔效應」(無限制嵌套導致重壓縮)。我想這是提問者試圖避免的。 –

1

這裏是一個非常簡單的和高度有效的AJAX鏈接/隊列插件。它會按順序依次執行您的ajax方法。

它的工作方式是接受一組方法,然後按順序執行它們。它在等待響應時不會執行下一個方法。

// ---這部分是你的代碼-----------------------

的$(document)。就緒(功能(){

var AjaxQ = []; 
AjaxQ[0] = function() { AjaxMethod1(); } 
AjaxQ[1] = function() { AjaxMethod2(); } 
AjaxQ[3] = function() { AjaxMethod3(); } 

//Execute methods in sequence 
$(document).sc_ExecuteAjaxQ({ fx: AjaxQ }); 

});

// ---這部分是AJAX PLUGIN -------------------

$ .fn。sc_ExecuteAjaxQ =功能(選件){

//? Executes a series of AJAX methods in dequence 

var options = $.extend({ 

    fx: [] //function1() { }, function2() { }, function3() { } 

}, options); 

if (options.fx.length > 0) { 

    var i = 0; 

    $(this).unbind('ajaxComplete'); 
    $(this).ajaxComplete(function() { 

     i++; 
     if (i < options.fx.length && (typeof options.fx[i] == "function")) { options.fx[i](); } 
     else { $(this).unbind('ajaxComplete'); } 

    }); 

    //Execute first item in queue 
    if (typeof options.fx[i] == "function") { options.fx[i](); } 
    else { $(this).unbind('ajaxComplete'); } 

} 

}

0
<script type="text/javascript"> 

    var promise1 = function() { 
     return new 
     $.Deferred(function (def) { 
      setTimeout(function() { 
       console.log("1"); 
       def.resolve(); 
      }, 3000); 
     }).promise(); 
    }; 

    var promise2 = function() { 
     return new 
     $.Deferred(function (def) { 
      setTimeout(function() { 
       console.log("2"); 
       def.resolve(); 
      }, 2000); 
     }).promise(); 
    }; 

    var promise3 = function() { 
     return new 
     $.Deferred(function (def) { 
      setTimeout(function() { 
       console.log("3"); 
       def.resolve(); 
      }, 1000); 
     }).promise(); 
    }; 

    var firstCall = function() { 
     console.log("firstCall"); 
     $.when(promise1()) 
     .then(function() { secondCall(); }); 
    }; 

    var secondCall = function() { 
     console.log("secondCall") 
     $.when(promise2()).then(function() { thirdCall(); }); 
    }; 

    var thirdCall = function() { 
     console.log("thirdCall") 
     $.when(promise3()).then(function() { console.log("done"); }); 
    }; 


    $(document).ready(function() { 
     firstCall(); 
    }); 
</script> 
0

我以爲我會離開這裏這個小練習的人誰可能會發現,我們建立請求的數組,當他們完成後,我們就可以觸發一個回調函數:

var urls = [{ 
    url: 'url1', 
    data: 'foo' 
}, { 
    url: 'url2', 
    data: 'foo' 
}, { 
    url: 'url3', 
    data: 'foo' 
}, { 
    url: 'url4', 
    data: 'foo' 
}]; 
var requests = []; 
var callback = function (result) { 
    console.log('done!'); 
}; 

var ajaxFunction = function() { 
    for (var request, i = -1; request = urls[++i];) { 
     requests.push($.ajax({ 
      url: request.url, 
      success: function (response) { 
       console.log('success', response); 
      } 
     })); 
    } 
}; 

// using $.when.apply() we can execute a function when all the requests 
// in the array have completed 
$.when.apply(new ajaxFunction(), requests).done(function (result) { 
    callback(result) 
}); 
1

答案CDR了,它具有目前最高的投票,是不對的。

當你有一個功能,B,C各返回$ .Deferred()對象,連鎖店如功能如下:

a().then(b).then(c) 

b和c皆會運行一次的承諾從返回已解決。由於這兩個那麼()函數綁的承諾,這個工程類同其他Jquery的鏈接,例如:

$('#id').html("<div>hello</div>").css({display:"block"}) 

其中兩個HTML()和CSS()函數被調用的對象從$返回( '#ID');

因此,爲了使A,B,C運行從以前的函數返回的承諾後得到解決,你需要做的是:

a().then(function(){ 
    b().then(c) 
}); 

這裏函數c的召喚是聯繫在一起的承諾,從返回功能b。

您可以用下面的代碼測試:

function a() { 
    var promise = $.Deferred(); 
    setTimeout(function() { 
     promise.resolve(); 
     console.log("a"); 
    }, 1000); 
    return promise; 
} 

function b() { 
    console.log("running b"); 
    var promise = $.Deferred(); 
    setTimeout(function() { 
     promise.resolve(); 
     console.log("b"); 
    }, 500); 
    return promise; 
} 

function c() { 
    console.log("running c"); 
    var promise = $.Deferred(); 
    setTimeout(function() { 
     promise.resolve(); 
     console.log("c"); 
    }, 1500); 
    return promise; 
} 

a().then(b).then(c); 
a().then(function(){ 
    b().then(c) 
}); 

變化的決心函數B()的承諾()拒絕(),你會看到其中的差別。

+0

cdr答案是對的。檢查此小提琴http://jsfiddle.net/0pb0g70y/完成您的代碼,爲清晰起見進行了一些更改。直到'b'結束,'c'纔會被調用。第二個'then'不適用於'a'的承諾,但是對於'b'返回的承諾(如果它確實返回承諾,在你的例子中就是這種情況,在cdr響應它的第二個'then') 。 –