2013-12-09 11 views
8

ich mehr asynchronen AJAX-Anfragen unter Verwendung von latenter/Versprechen Implementierung von jquery Warteschlange will:Warten auf Abschluss nach mehreren Versprechen parallel mit jQuery

function doSomething() { 
    console.log('doSomething')}; 

function makeMultiAjaxRequests1() { 
    console.log('makeMultiAjaxRequests1')}; 

function makeMultiAjaxRequests2() { 
    console.log('makeMultiAjaxRequests2')}; 

var step1 = function() { 
    var promise = new $.Deferred().promise(); 
    makeMultiAjaxRequests1(); 
    return promise; } 

var step2 = function() { 
    var promise = new $.Deferred().promise(); 
    makeMultiAjaxRequests2(); 
    return promise; } 

step1() 
    .then(step2()) 
    .done(doSomething()); 

$.when(step1(), 
     step2()) 
    .done(function() { 
    doSomething(); 
}); 

Hier sind die fiddle link. Also meine Frage ist:

In dem Muster, wo Schritt1 und Schritt2 parallel ausgeführt werden, erreicht der Code nicht die letzte Handler-Funktion. Warum?

+0

Wo aufgelöst Sie tatsächlich das Versprechen? Wenn Sie den Handler nicht auslösen, wird der Callback nicht aufgerufen ... – Bergi

+0

Die Deferreds in 'step1()' und 'step2()' werden nie aufgelöst. –

+0

Ja das stimmt, aber was ist der Fall im vorherigen sequenziellen Beispiel? Das Versprechen ist nicht gelöst und der Code ist immer noch vollendet. – crishushu

Antwort

0

Es macht erreichen Ihre done Funktion, wenn Sie eine URL geben kann es tatsächlich (im Falle von jsfiddle zu erreichen, das wäre sagen /echo/html/: http://jsfiddle.net/LnaPt/2/

Im Grunde, die Sie gerade dies tun müssen, um:

var promise = $.ajax({ 
    type: "GET", 
    url: "/echo/html/", //<-- instead of google  
}).promise(); 
6

Sie müssen die deferred obj in Schritt 1 und Schritt 2 lösen

Versuchen Sie, diese

function doSomething() { 
    console.log('doSomething')}; 

function makeMultiAjaxRequests1(deferred) { 
    console.log('makeMultiAjaxRequests1') 
    deferred.resolve()}; 

function makeMultiAjaxRequests2(deferred) { 
    console.log('makeMultiAjaxRequests2') 
    deferred.resolve()}; 

var step1 = function() { 
    var deferred = new $.Deferred(); 
    makeMultiAjaxRequests1(deferred); 
    return deferred; } 

var step2 = function() { 
    var deferred = new $.Deferred(); 
    makeMultiAjaxRequests2(deferred); 
    return deferred; } 

step1().then(step2).done(doSomething); 

$.when(step1(), step2()).done(function() { 
    doSomething(); 
}); 
+1

Danke. Eine Frage zu Ihrem Vorschlag: Warum nicht deferred.promise() in den Schritten zurückgeben? Wo ist der Unterschied, wenn wir Versprechungen zurückgeben würden? – crishushu

+0

@crishushu Verzögerung und versprechen, beide haben dann, Methoden gemacht. Aber versprechen Sie, haben Sie nicht Lösungsmethode. – Daiwei

+0

meine Frage bezieht sich auf das Verhalten der sequentiellen Fall (step1(). Dann (step2) .done (doSomething);). Dort macht es keinen Unterschied, ob wir das zurückgestellte Objekt zurückgeben oder ob wir sein Versprechen zurückgeben; beide werden doSomething() – crishushu

4

@Daiwei gibt eine gute Antwort.

Ein allgemeiner Bezugspunkt ist https://gist.github.com/sergio-fry/3917217 von sergio-fry.

Sollten Sie einen dynamischeren Ansatz haben wollen, wo man vorher nicht wissen, wie viele Argumente, die Sie parallel laufen, ist hier ein gutes Beispiel Erweiterung von JQuery (1.10+):

$.whenAll = function (deferreds) { 
    function isPromise(fn) { 
     return fn && typeof fn.then === 'function' && 
      String($.Deferred().then) === String(fn.then); 
    } 
    var d = $.Deferred(), 
     keys = Object.keys(deferreds), 
     args = keys.map(function (k) { 
      return $.Deferred(function (d) { 
       var fn = deferreds[k]; 

       (isPromise(fn) ? fn : $.Deferred(fn)) 
        .done(d.resolve) 
        .fail(function (err) { d.reject(err, k); }) 
       ; 
      }); 
     }); 

    $.when.apply(this, args) 
     .done(function() { 
      var resObj = {}, 
       resArgs = Array.prototype.slice.call(arguments); 
      resArgs.forEach(function (v, i) { resObj[keys[i]] = v; }); 
      d.resolve(resObj); 
     }) 
     .fail(d.reject); 

    return d; 
}; 

Siehe Code in Aktion mit einem dynamischen anschaulichen Beispiel:

http://jsbin.com/nuxuciwabu/edit?js,console

Verwandte Themen