2014-07-11 30 views
9

Basit bir dizi URL'im var ve her birini jQuery ile yüklemek istiyorum. $.get kullanıyordum, ancak $.Deferred ile çalışmaya başlayamıyorum, bu yüzden $.ajax'a geçtim - neredeyse çalışıyorum, ama elde ettiğim sonuçlar .. tuhaf. Birinin bu işi daha iyi yapmam için bana yardımcı olabileceğini umuyordum.

var results = [], files = [ 
    'url1', 'url2', 'url3' 
]; 

$.when(
    $.ajax(files[0]).done(function(data) { 
     results.push(data); console.log("step 1.0"); 
    }), 
    $.ajax(files[1]).done(function(data) { 
     results.push(data); console.log("step 1.1"); 
    }), 
    $.ajax(files[2]).done(function(data) { 
     results.push(data); console.log("step 1.2"); 
    }) 
).then(function(){ 
    console.log("step 2"); 
}); 

Bu çıktılayacaktır ..

  • adım 1.0
  • adım 1.1
  • adım 1.2
  • sonra results dizi sonucu içeren 2

ve adım Tüm 3 ajax istekleri. Mümkün mü?

+1

Bu konuda yaşadığınız sorun nedir? İstekler farklı bir sırayla tamamlanabilir, böylece 'adım 1.2, adım 1.0, adım 1.1, adım 2' ile sonlanabilir, ancak dizi her zaman "o zaman"() yürütüldükten sonra doldurulur. –

+0

Doğru sırada tamamlamaları için kesinlikle onlara ihtiyacım var. Kodun doğru çalışması önemlidir. – Ciel

+0

Farklı sonuçlar alıyorum.Adım 1’lerden herhangi birinde adım 2’yi kovuyorum. – Ciel

cevap

8

İlk kapalı .her geçirildi sırayla olacak .sonra geçirilen

var results = [], files = [ 
    'url1', 'url2', 'url3' 
]; 

$.when.apply($, $.map(files, function (file) { 
    return $.ajax(file); 
})).then(function (dataArr) { 
    /* 
    * dataArr is an array of arrays, 
    * each array contains the arguments 
    * returned to each success callback 
    */ 
    results = $.map(dataArr, function (data) { 
     return data[0]; // the first argument to the success callback is the data 
    }); 
    console.log(results); 
}); 

argümanlar, size (sizin üç ajax paralel olarak işlenecek çağrıları istiyorsanız karar vermek zorunda Hepsi aynı anda, daha az genel çalışma süresiyle) veya bir ajax çağrısının çalıştığı sırada tamamlanır ve bir sonraki ajax çağrısını başlatırsınız. Bu, bunu nasıl yaptığınızı etkileyen önemli bir tasarım kararıdır.

$.when()'u kullandığınızda, paralel olarak tüm üç ajax çağrısını başlatıyorsunuz. Sonuçların tümünü yalnızca tamamladığınızda incelerseniz, sonuçları belirli bir sırayla işleyebilirsiniz (yalnızca tüm sonuçlar kullanılabilir olduğunda işlenecek ve talep edilen sırada mevcut olacaktır). Ancak, bu şekilde yapıldığında, tüm ajax çağrıları başlangıçta bir kerede gönderilecektir. Bu, size daha iyi bir uçtan uca zaman kazandıracaktır, eğer bu istek türleri için uygunsa, bu genellikle bunu yapmak için daha iyi bir yoldur.

Bunu yapmak için, size böyle bir şey için ne yeniden yapılandırabilir: Eğer adı olmuştur $.when() için .done() işleyicisi kadar bekliyoruz Çünkü

Paralel
var files = [ 
    'url1', 'url2', 'url3' 
]; 

$.when($.ajax(files[0]),$.ajax(files[1]),$.ajax(files[2])).done(function(a1, a2, a3) { 
    var results = []; 
    results.push(a1[0]); 
    results.push(a2[0]); 
    results.push(a3[0]); 
    console.log("got all results") 
}); 
yılında

Run, Tüm ajax sonuçları bir kerede hazırdır ve $.when() tarafından talep edildikleri sırayla sunulur (hangisinin önce gerçekten bittiğine bakılmaksızın), böylece sonuçları olabildiğince çabuk alırsınız ve tahmin edilebilir bir sırada sunulurlar.

Not, results dizininin tanımını da $.when() bitmiş işleyiciye taşıdım çünkü bu, verilerin gerçekten geçerli olduğunu bildiğiniz tek yer (zamanlama nedenleriyle).Paralel içinde


Run - Eğer daha uzun bir dizi olsaydı, daha iyi yerine bir döngü içinde hepsini işlemek için .map() gibi bir şey ile dizi yineleme yapmak bulabilir Keyfi Uzunluk Dizisi

Iterate bunları tek tek sıralamak yerine:

var files = [ 
    'url1', 'url2', 'url3', 'url4', 'url5', 'url6', 'url7' 
]; 

$.when.apply($, files.map(function(url) { 
    return $.ajax(url); 
})).done(function() { 
    var results = []; 
    // there will be one argument passed to this callback for each ajax call 
    // each argument is of this form [data, statusText, jqXHR] 
    for (var i = 0; i < arguments.length; i++) { 
     results.push(arguments[i][0]); 
    } 
    // all data is now in the results array in order 
}); 

Sıra Ajax Çağrılar

Öte yandan, ajax çağrılarınızı sıralamak istiyorsanız, 2. birincisi ilk iş bitene kadar başlamıyorsa (2. ajax çağrısının sonuçlanması gerekiyorsa gerekli olabilecek bir şey) Ne istemek ya da yapmak için bilmek için ilk ajax çağrısı), o zaman tamamen farklı bir tasarım desenine ihtiyacınız var ve $.when() hiçbir şekilde gitmek değildir (sadece paralel istekleri yapar). Bu durumda, muhtemelen sonuçlarınızı x.then().then() ile zincirlemek istersiniz ve daha sonra, günlük ifadelerini istediğiniz gibi sıralayabilirsiniz.

$.ajax(files[0]).then(function(data0) { 
     console.log("step 1.0"); 
     return $.ajax(files[1]); 
    }).then(function(data1) { 
     console.log("step 1.1"); 
     return $.ajax(files[2]); 
    }).done(function(data2) { 
     console.log("step 1.2"); 
     // all the ajax calls are done here 
     console.log("step 2"); 
    }); 

Konsol Çıktı:

step 1.0 
step 1.1 
step 1.2 
step 2 

Bu yapı aynı zamanda dosyaların sizin dizisi uzun ise otomatik N sıralı ajax çağrıları için çalıştırmak için bir döngü içine konabilir. results dizisine gittiğinizde sonuçları toplayabilseniz de, çoğu zaman sıralı olarak yapılmasının nedeni, önceki sonuçların bir sonraki ajax çağrısı tarafından tüketilmesidir, bu yüzden genellikle yalnızca nihai sonuca ihtiyacınız olur. Sonuçlarınızı istediğiniz gibi toplamak isterseniz, bunları her adımda results dizisine kesinlikle zorlayabilirsiniz.

Dikkat edin, vaat edilen avantajlar, aynı üst düzey yuvada kalırken ve daha fazla iç içe geçmedikçe işlemleri sıralayabilirsiniz.


Sıra Ajax Aramalar - Iterate Keyfi Uzunluk Dizisi İşte

sıralama bir döngü içinde nasıl görüneceğini var:

var files = [ 
    'url1', 'url2', 'url3', 'url4', 'url5', 'url6', 'url7' 
]; 

var results = []; 
files.reduce(function(prev, cur, index) { 
    return prev.then(function(data) { 
     return $.ajax(cur).then(function(data) { 
      console.log("step 1." + index); 
      results.push(data); 
     }); 
    }) 
}, $().promise()).done(function() { 
    // last ajax call done 
    // all results are in the results array 
    console.log("step 2.0"); 
}); 

Konsolundan Çıkışı:

step 1.0 
step 1.1 
step 1.2 
step 1.3 
step 1.4 
step 1.5 
step 1.6 
step 2 

Array.prototype.reduce() yöntemi wo Burada her bir dizi eleman için .then() ekledikçe yapmanız gereken her bir bireysel elemanını işlerken tek bir değer biriktirdiği için burada rpt handily. .reduce() yineleme, $().promise() ile boş/çözülmüş bir sözle (bu tür bir vaat oluşturmanın başka yolları da vardır) başlatılmıştır, bu da bize zaten çözülmüş olan .then()'u yapmaya başlamak için bir şey verir.

+0

Bu son derece yararlıdır. Olası bir ek yük ile bile, harici bir kütüphane kullanma bilgeliğini görmeye başlıyorum. Şu anda bunu sadece bir yerde yapmam gerekiyor, ancak iki veya daha fazla kez yapmam gerekirse, bunu yapmak için ekstra çalışma miktarı daha fazla zarar veriyor. – Ciel

+0

@Ciel - Yorumunuzu anlamıyorum. Neden harici bir kütüphaneye ihtiyacınız var? Bu seçeneklerden herhangi birini, yalnızca birkaç kod satırıyla yeniden kullanılabilir bir işleve dönüştürebilirsiniz. – jfriend00

+0

Üzgünüm. Biraz dikkatimi dağıttım ve bugün sadece bunu denemek için şansım oldu. Tüm yardımlarınız için çok teşekkür ederim, bu örnekten sadece çok şey öğrendim. – Ciel

2

Her bir .done yerine .then değerlerinden dönüş değerlerine erişmelisiniz. Ayrıca, arkadaşınız .map. onlar

+1

Verileri doğru bir şekilde $ .when() 'dan ele aldığınızı düşünmüyorum. Bir dizi dizi olan tek bir argüman vermez. Her argümanın üç değer dizisi olduğu bir dizi argüman verir. İkinci kodun sonundaki örneğe bakın http://api.jquery.com/jquery.when/ on line 3. – jfriend00