two parallel calls either one succeeds in javascri

2019-08-07 03:02发布

I want something like the async library to do two parallel calls either one succeeds in javascript and then the callback to operate on the succeeded output. It does not seem that async has that. parallel would err out if either one fails.

In general, if I have N tasks, and I want to guarantee m succeed and use the output from these m calls, how can I do it?

2条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-08-07 03:19

You can use jQuery.Deferred and jQuery.when to achieve this (there are other promise libraries too).

var d1 = $.Deferred();
var d2 = $.Deferred();

$.when( d1, d2 ).done(function ( v1, v2 ) {
   // this will execute only when both deferred objects are resolved
   // and the values passed to those for resolving will be available 
   // through v1 and v2
});

$.get('url1').success(function() { d1.resolve('value for v1') });
$.get('url2').success(function() { d2.resolve('value for v2') });

jQuery.when: https://api.jquery.com/jQuery.when/

jQuery.Deferred: https://api.jquery.com/category/deferred-object/

查看更多
贪生不怕死
3楼-- · 2019-08-07 03:39

Promise.race

You want Promise.race (assuming you are willing to move from async to promises):

Promise.race([d1, d2]) . then(result =>

From MDN:

The Promise.race method returns a promise that resolves or rejects as soon as one of the promises in the iterable resolves or rejects, with the value or reason from that promise.

Writing race in callback fashion

As far as I can see async does not provide the equivalent of race, but you can do something like:

async.race = function(tasks, callback) {
  var done = false;
  tasks.forEach(function(task) {
    task(function(err, data) {
      if (done) return;            // another task finished first
      done = true;
      callback(err, data);
    });
  });
};

Perhaps you want a variant of race where errors are ignored--although that design seems questionable. In that case:

async.firstFulfilled = function(tasks, callback) {
  var done = false;
  tasks.forEach(function(task) {
    task(function(err, data) {
      if (err || done) return;    // skip failures
      done = true;
      callback(err, data);
    });
  });
};

Return first n non-error cases:

async.firstNFulfilled = function(n, tasks, callback) {
  var result = [];
  tasks.forEach(function(task) {
    task(function(err, data) {
      if (err) return;
      result.push(data);
      if (!--n) callback(null, result);
    });
  });
};
查看更多
登录 后发表回答