2012-06-18 2 views
5

그래서 인터뷰에서이 질문을 받았지만 좋은 유스 케이스가 나타났습니다. 데이터 소스가 여러 개 있다고 가정합니다. 첫 번째 가능한 것을 찾고 처리하고 나머지는 무시하고 싶습니다.jQuery Deferred를 사용하여 첫 번째로 사용 가능한 데이터 소스 찾기

그래서 같은 :

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");}); 

배열을 (어쩌면 않습니다) 수락 할 때 정말 생각하지 않는 것이 무시합니다. 이것은 물론 그들이 모두 완료 될 때까지 기다리게 할 것입니다. 그 중 하나가 완료 될 때까지 기다릴 수있는 코드를 찾고, 나머지는 걱정하지 않아야합니다.

재귀 적으로 만 작동한다는 알림을 받았습니다.

+0

그들은 모두 첫 번째 실패 두 번째를 동시에 시작하거나해야 : 당신이 jQuery를 장착 한 후에

는 바로이 코드를 드롭? – Bergi

+0

@Bergi 어느 것이 든 작동한다고 생각합니다. 둘 다 다양한 사용 사례에서 최적이라고 생각합니다. – Parris

+0

예,하지만 그 개념은 매우 다릅니다. 그래서 어느 것이 필요합니까? – Bergi

답변

3

이것은 재귀를 사용하지 않지만 여러 데이터 소스에서 가져 오는 요구 사항에 적합하며 성공적인 응답을 반환하는 첫 번째 매개 변수에만주의를 기울입니다. 내가 반대 의미와 $.when()의 다른 버전을 제공하는 플러그인을했습니다

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

이것은 실제로 아주 멋지며, 한 번에 모두 시작할 수 있습니다! 아마도 다른 look ups도 막을 수있는 방법이있을 것입니다. – Parris

+1

@Parris 확실히, 지연을 어딘가에 저장하고'anyComplete' 핸들러에서'abort'를 호출하십시오. 나는 그것을 편집했다. – Esailija

1

http://jsfiddle.net/mNJ6D/

. $.when()의 실제 jQuery 구현에서 수정되었으므로 처음에는 resolve d 약속을 기다리거나 reject에 대한 약속을 제외하고는 원본과 완전히 동일합니다.

(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); 
관련 문제