node.js 多個異步過程判斷執行是否完成

場景:想請求量較大的網絡數據,好比想獲取1000條結果,但數據處理速度慢,有超時的風險,能夠分紅10次處理,每次處理100條;全部請求完成後再統一進行處理。git

這樣的應用場景,能夠這樣處理:github

方案一:判斷請求到的數據條目

// 模擬網絡請求
function fetch(url, callback) {
  setTimeout(function (){
    callback(null, {
        subjects: [{
          data: Math.round(Math.random() * 100)
        }]
      });
  }, 2000);
}

// 實現方案1
function multiTask_1 () {
  var arr = [];
  var baseUrl = 'https://api.douban.com/v2/movie/top250';
  for (var start = 0; start < 10; start++) {
    var url = baseUrl + '?start=' + start + "&count=1";
      fetch(url, function(error, res) {
        var data = res.subjects;
        arr = arr.concat(data);
        // 調用完成後統一處理
        if (arr.length === 10) {
          console.log(arr);
        }
    });
  }
}

將運行結果用arr.length來判斷,若是arr.length不像咱們指望的那樣,好比因爲網絡傳輸或者處理異常,少一條,那麼咱們將沒法作後續的處理。這種處理方式強業務耦合;不具備普適性。api

方案二:判斷異步過程執行次數

// 方案2
function multiTask_2 () {
  var taskWatcher = 0;
  var arr = [];
  var baseUrl = 'https://api.douban.com/v2/movie/top250';
  for (var start = 0; start < 10; start++) {
    taskWatcher++;
    var url = baseUrl + '?start=' + start + "&count=1";
    fetch(url, function(error, res) {
        var data = res.subjects;
        arr = arr.concat(data);
        taskWatcher--;
        if (taskWatcher === 0) {
          console.log(arr);
        }
    });
  }
}

方案2 的判斷條件,這裏的 taskWatcher 充當異步任務執行狀況的觀察員,
僅與異步過程的調用次數有關,且與其餘處理過程無關。那有沒有其餘方案呢數組

方案三:Promise.all()

Promise.all(iterable) 方法返回一個 Promise, 它將在上述可迭代對象中的全部 Promise 被 resolve 以後被 resolve,或者在任一 Promise 被 reject 後被 reject。網絡

function multiTask_3 () {
  // var taskWatcher = 0;
  var taskStack = [];
  var arr = [];
  var baseUrl = 'https://api.douban.com/v2/movie/top250';
  for (var start = 0; start < 10; start++) {
    taskStack.push(
      new Promise((resolve, reject) => {
        var url = baseUrl + '?start=' + start + "&count=1";
        fetch(url, function(error, res) {
          var data = res.subjects;
          arr = arr.concat(data);
          resolve();
        });
      })
    );
  }

  Promise.all(taskStack).then(function () {
    console.log(arr);
  });
}

這種方式更具備通用性,若是異步任務類型不一樣,也能夠用這種方式來解決。不過應當注意reject的處理。避免其對最終處理的影響。dom

方案四: EventProxy

EventProxy是樸靈寫的,https://github.com/JacksonTian/eventproxy異步

var ep = new EventProxy();
  var arr = [];
  ep.after('fetchData', 10, function (list) {
    list.forEach(function(item){
      arr = arr.concat(item); 
    });
    console.log(arr);
  });

  var baseUrl = 'https://api.douban.com/v2/movie/top250';
  for (var start = 0; start < 10; start++) {
    var url = baseUrl + '?start=' + start + "&count=1";
      fetch(url, function(error, res) {
        var data = res.subjects;
        ep.emit('fetchData', data);
    });
  }

EventProxy基於事件訂閱/發佈模式,這裏的after 方法能夠偵聽屢次事件,回調中保存了屢次異步任務的數據結果的數組;除此以外EventProxy還支持多個不一樣事件的偵聽和處理。fetch

相關文章
相關標籤/搜索