Find first available data source with jQuery Deferred

拜拜、爱过 提交于 2019-12-04 07:44:24

This doesn't use recursion but fits the requirement to fetch from multiple datasources and only care about the first that returns a successful response.

http://jsfiddle.net/mNJ6D/

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

I've made a plugin which provides another version of $.when() with reversed semantics. It's modified from the actual jQuery implementation of $.when() so it's exactly the same as the original except that it waits for either the first resolved promise, or all promised to be rejected.

Just drop this code in right after you load jQuery:

(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);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!