同步與異步

提到異步,腦子里跳出來的第一個詞是ajax異步加載,異步即相互不影響,總感覺異步離我很遠,直到去看了相關(guān)的文檔,瞬間恍然大悟。

1. 單線程

首先了解下,JavaScript是采用的是單線程模型(JavaScript 同時只能執(zhí)行一個任務(wù),其他任務(wù)都必須在后面排隊等待)

2. 同步任務(wù)和異步任務(wù)

程序里面的所有任務(wù),簡單分成兩類:同步任務(wù)(synchronous)和異步任務(wù)(asynchronous)。

同步任務(wù)

是那些沒有被引擎掛起、在主線程上排隊執(zhí)行的任務(wù)。只有前一個任務(wù)執(zhí)行完畢,才能執(zhí)行后一個任務(wù)。

異步任務(wù)

是那些被引擎放在一邊,不進入主線程、而進入任務(wù)隊列的任務(wù)。只有引擎認為某個異步任務(wù)可以執(zhí)行了(比如 Ajax 操作從服務(wù)器得到了結(jié)果),該任務(wù)(采用回調(diào)函數(shù)的形式)才會進入主線程執(zhí)行。排在異步任務(wù)后面的代碼,不用等待異步任務(wù)結(jié)束會馬上運行,也就是說,異步任務(wù)不具有”堵塞“效應(yīng)。
(搬運過來的概念)

口語化,同步就是一個一個地執(zhí)行,后面的在排隊等待。異步就是一個在執(zhí)行,異步不在等待的隊伍中,當(dāng)達到了觸發(fā)異步的點,異步被調(diào)用執(zhí)行,異步執(zhí)行完了繼續(xù)按照原來的順序來執(zhí)行任務(wù)。

3. 任務(wù)隊列和事件循環(huán)

首先,主線程會去執(zhí)行所有的同步任務(wù)。等到同步任務(wù)全部執(zhí)行完,就會去看任務(wù)隊列里面的異步任務(wù)。如果滿足條件,那么異步任務(wù)就重新進入主線程開始執(zhí)行,這時它就變成同步任務(wù)了。等到執(zhí)行完,下一個異步任務(wù)再進入主線程開始執(zhí)行。一旦任務(wù)隊列清空,程序就結(jié)束執(zhí)行。

異步任務(wù)的寫法通常是回調(diào)函數(shù)。一旦異步任務(wù)重新進入主線程,就會執(zhí)行對應(yīng)的回調(diào)函數(shù)。如果一個異步任務(wù)沒有回調(diào)函數(shù),就不會進入任務(wù)隊列,也就是說,不會重新進入主線程,因為沒有用回調(diào)函數(shù)指定下一步的操作。

(概念有點暈)

4. 異步操作的幾種模式

4.1 回調(diào)函數(shù)
同步:

function f1() {
  // ...
}

function f2() {
  // ...
}

f1();
f2();

異步:

function f1(callback) {
  // ...
  callback();
}

function f2() {
  // ...
}

f1(f2);

4.2 事件監(jiān)聽
異步的執(zhí)行不取決于代碼的順序,而取決于某個事件(觸發(fā)它的點)是否發(fā)生。

f1.on('done', f2);
function f1() {
  setTimeout(function () {
    // ...
    f1.trigger('done');
  }, 1000);
}

4.3 發(fā)布/訂閱
可以理解為事件監(jiān)聽的另一種形式。
優(yōu)勢:可以通過查看“消息中心”,了解存在多少信號、每個信號有多少訂閱者,從而監(jiān)控程序的運行。

jQuery.subscribe('done', f2);  //訂閱
function f1() {                       
  setTimeout(function () {
    // ...
    jQuery.publish('done');     //訂閱
  }, 1000);
}
  1. 異步操作的流程控制
    如果有多個異步操作,就存在一個流程控制的問題:如何確定異步操作執(zhí)行的順序,以及如何保證遵守這種順序。
    5.1 串行執(zhí)行
var items = [ 1, 2, 3, 4, 5, 6 ];
var results = [];

function async(arg, callback) {
  console.log('參數(shù)為 ' + arg +' , 1秒后返回結(jié)果');
  setTimeout(function () { callback(arg * 2); }, 1000);
}

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

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

series(items.shift());

(一開始看了半個鐘沒get到點)
5.2 并行執(zhí)行
流程控制函數(shù)也可以是并行執(zhí)行,即所有異步任務(wù)同時執(zhí)行,等到全部完成以后,才執(zhí)行final函數(shù)。

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

function async(arg, callback) {
  console.log('參數(shù)為 ' + arg +' , 1秒后返回結(jié)果');
  setTimeout(function () { callback(arg * 2); }, 1000);
}

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

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

看完才知道,原來我日常寫的都是異步?。≈皇菦]有一個很清晰的概念,有回調(diào)函數(shù)的都是異步啦(這樣立即應(yīng)該沒錯吧)
5.3 并行與串行的結(jié)合
所謂并行與串行的結(jié)合,就是設(shè)置一個門檻,每次最多只能并行執(zhí)行n個異步任務(wù),這樣就避免了過分占用系統(tǒng)資源。
(看到這感覺可以忽略掉后面的代碼了)

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

function async(arg, callback) {
  console.log('參數(shù)為 ' + arg +' , 1秒后返回結(jié)果');
  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();

記錄此文,方便日后翻閱有關(guān)異步的相關(guān)知識點,大部分內(nèi)容來源于網(wǎng)絡(luò)。
傳送門:
https://wangdoc.com/javascript/async/general.html#%E5%BC%82%E6%AD%A5%E6%93%8D%E4%BD%9C%E7%9A%84%E6%B5%81%E7%A8%8B%E6%8E%A7%E5%88%B6

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • “轉(zhuǎn)眼間,入場區(qū)塊鏈數(shù)字貨幣投資已經(jīng)有兩個星期了,簡單地總結(jié)下這兩周的事情吧。 首先,對自己能夠開始對新鮮事物保持...
    寶爺說幣閱讀 610評論 1 0
  • 練習(xí)24:輸入輸出和文件 原文:Exercise 24: Input, Output, Files 譯者:飛龍 你...
    布客飛龍閱讀 369評論 0 35
  • 走著走著,俺叫孫悟空。俺是齊天大圣,妖魔鬼怪休想逃出我的火眼金睛。我有七十二變可以變魚變兔子也可以變成陸地之王老虎...
    海風(fēng)八里閱讀 429評論 0 1
  • “管理花兒團隊”!管理,花兒,兩個好像有點格格不入的名詞。但當(dāng)組合在一起成為一個團隊的名稱時就有了一點剛?cè)岵母?..
    紅雨的日記閱讀 917評論 0 3

友情鏈接更多精彩內(nèi)容