2012-06-18 11 views
5

Bu yüzden bir röportajda sordum, ama iyi bir kullanım durumu ortaya çıkardı. Bir sürü veri kaynağınız olduğunu varsayalım. İlk müsait olanı bulmak ve işlemek ve geri kalanını görmezden gelmek istiyorsunuz.jQuery ile ilk kullanılabilir veri kaynağını bul Deferred

Yani böyle bir şey:

var datasources = new Array("somedatabase1/pizza","somedatabase2/beer","somedatabase3/llama"); 
var dfds = new Array(); 
$.each(datasources,function(source){ 
    dfds.push($.getJSON(source)); 
}); 

$.when(dfds).done(function(){alert("they are all done");}); 

bir dizi (belki öyle) kabul ettiğinde gerçekten sanmıyorum geçiyoruz. Elbette hepsi tamamlanana kadar bekleyecekti. Birini beklemek, herhangi biri bitene kadar beklemek ve sonra başkaları için endişelenmemek için bir kod arıyorum.

Sadece yinelemeli çalışacağını öğrendim.

+0

hepsi birinci başarısız ikincisini aynı anda başlamak mı yoksa: jQuery yüklemek sonra

Sadece sağ Bu kodu damla? – Bergi

+0

@Bergi Bence işe yarayacak, bence her ikisi de çeşitli kullanım durumlarında optimal. – Parris

+0

Evet, ama onların konsepti çok farklı. Hangisine ihtiyacınız var? – Bergi

cevap

3

Bu, özyinelemeyi kullanmaz, ancak birden çok veri kaynağından alma gereksinimini karşılar ve yalnızca başarılı bir yanıt veren ilk öğeyi dikkate alır. Ben ters semantik ile $.when() başka bir sürümünü sağlayan bir eklenti yaptık

function raceToIt(urls) { 
    var deferred = $.Deferred(), 
     promises; 

    function anyComplete(data) { 
     if (!deferred.isResolved()) { 
      deferred.resolveWith(this, [data]); 
      promises.forEach(function(promise) { 
       promise.abort(); 
      }); 
     } 
    } 
    promises = urls.map(function(url) { 
     return $.getJSON(url).then(anyComplete); 
    }); 
    return deferred.promise(); 
} 
raceToIt(["/echo/json/", "/echo/json/", "/echo/json/"]).then(function(data) { 
    console.log(data); 
});​ 
+0

Bu aslında oldukça harika ve hepsini bir seferde başlatmanıza izin veriyor! Belki de diğer bakışları da durdurmanın bir yolu vardır. – Parris

+1

@Parris emin olun, sadece ertelenen bir yerde saklayın ve 'anyComplete' işleyicide 'iptal' olarak adlandırın. Onu düzenledim. – Esailija

1

http://jsfiddle.net/mNJ6D/

. $.when()'un asıl jQuery uygulamasından değiştirildiğinden, ilk resolve d sözü veya reject ed için söz verilmiş olması hariç, orijinaliyle tam olarak aynıdır.

(function($) { 
    $.reverseWhen = function(subordinate /* , ..., subordinateN */) { 
    var i = 0, 
     rejectValues = Array.prototype.slice.call(arguments), 
     length = rejectValues.length, 

     // the count of uncompleted subordinates 
     remaining = length !== 1 || (subordinate && jQuery.isFunction(subordinate.promise)) ? length : 0, 

     // the master Deferred. If rejectValues consist of only a single Deferred, just use that. 
     deferred = remaining === 1 ? subordinate : jQuery.Deferred(), 

     // Update function for both reject and progress values 
     updateFunc = function(i, contexts, values) { 
     return function(value) { 
      contexts[ i ] = this; 
      values[ i ] = arguments.length > 1 ? Array.prototype.slice.call(arguments) : value; 
      if(values === progressValues) { 
      deferred.notifyWith(contexts, values); 
      } else if (!(--remaining)) { 
      deferred.rejectWith(contexts, values); 
      } 
     }; 
     }, 

     progressValues, progressContexts, rejectContexts; 

    // add listeners to Deferred subordinates; treat others as rejected 
    if (length > 1) { 
     progressValues = new Array(length); 
     progressContexts = new Array(length); 
     rejectContexts = new Array(length); 
     for (; i < length; i++) { 
     if (rejectValues[ i ] && jQuery.isFunction(rejectValues[ i ].promise)) { 
      rejectValues[ i ].promise() 
      .done(deferred.resolve) 
      .fail(updateFunc(i, rejectContexts, rejectValues)) 
      .progress(updateFunc(i, progressContexts, progressValues)); 
     } else { 
      --remaining; 
     } 
     } 
    } 

    // if we're not waiting on anything, reject the master 
    if (!remaining) { 
     deferred.rejectWith(rejectContexts, rejectValues); 
    } 

    return deferred.promise(); 
    }; 
})(jQuery); 
İlgili konular