1. 程式人生 > >js非同步操作的流程控制——20181114

js非同步操作的流程控制——20181114

序列執行(程式碼可直接在console控制檯執行)

var items = [ 1, 2, 3, 4, 5, 6 ];
var results = [];

function async(arg, callback) {
  console.log('引數為 ' + arg +' , 1秒後返回結果');
  setTimeout(function () { callback(arg * 2); }, 1000);
}

function final(value) {
  console.log('完成: ', value);
}

function series(item) {
  if(item) {
    console.log('lalala');
    async( item, function(result) {
      console.log('bbb');
      results.push(result);
      console.log(result);
      return series(items.shift());
    });
  } else {
    return final(results[results.length - 1]);
  }
}

series(items.shift());

上面的寫法需要六秒,才能完成整個指令碼。

並行執行

var items = [ 1, 2, 3, 4, 5, 6 ];
var results = [];

function async(arg, callback) {
  console.log('引數為 ' + arg +' , 1秒後返回結果');
  setTimeout(function () { callback(arg * 2); }, 1000);
}

function final(value) {
  console.log('完成: ', value);
}

items.forEach(function(item) {
  async(item, function(result){
    console.log('bbb');
    results.push(result);
    console.log(result);
    if(results.length === items.length) {
      final(results[results.length - 1]);
    }
  })
});

上面程式碼中,forEach方法會同時發起六個非同步任務,等到它們全部完成以後,才會執行final函式。

相比而言,上面的寫法只要一秒,就能完成整個指令碼。這就是說,並行執行的效率較高,比起序列執行一次只能執行一個任務,較為節約時間。但是問題在於如果並行的任務較多,很容易耗盡系統資源,拖慢執行速度。因此有了第三種流程控制方式。

並行與序列的結合

所謂並行與序列的結合,就是設定一個門檻,每次最多隻能並行執行n個非同步任務,這樣就避免了過分佔用系統資源。

var items = [ 1, 2, 3, 4, 5, 6 ];
var results = [];
var running = 0;
var limit = 2;

function async(arg, callback) {
  console.log('引數為 ' + arg +' , 1秒後返回結果');
  setTimeout(function () { callback(arg * 2); }, 1000);
}

function final(value) {
  console.log('完成: ', value);
}

function launcher() {
  while(running < limit && items.length > 0) {
    var item = items.shift();
    async(item, function(result) {
      results.push(result);
      running--;
      if(items.length > 0) {
        launcher();
      } else if(running == 0) {
        final(results);
      }
    });
    running++;
  }
}

launcher();