第六次:異步操作參考問題

學(xué)習(xí)教材為:https://wangdoc.com/javascript/async/index.html

1 如何理解JS的單線程模型?單線程模型優(yōu)劣勢?

單線程模型指的是,JavaScript 只在一個線程上運(yùn)行。也就是說,JavaScript 同時只能執(zhí)行一個任務(wù),其他任務(wù)都必須在后面排隊等待。

2 JavaScript 引擎都有哪些線程?

JavaScript 引擎有多個線程,單個腳本只能在一個線程上運(yùn)行(稱為主線程),其他線程都是在后臺配合。

3 什么是同步任務(wù)和異步任務(wù)?

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

4 如何理解JS引擎提供的任務(wù)隊列?

首先,主線程會去執(zhí)行所有的同步任務(wù)。等到同步任務(wù)全部執(zhí)行完,就會去看任務(wù)隊列里面的異步任務(wù)。如果滿足條件,那么異步任務(wù)就重新進(jìn)入主線程開始執(zhí)行,這時它就變成同步任務(wù)了。等到執(zhí)行完,下一個異步任務(wù)再進(jìn)入主線程開始執(zhí)行。一旦任務(wù)隊列清空,程序就結(jié)束執(zhí)行。
異步任務(wù)的寫法通常是回調(diào)函數(shù)。一旦異步任務(wù)重新進(jìn)入主線程,就會執(zhí)行對應(yīng)的回調(diào)函數(shù)。如果一個異步任務(wù)沒有回調(diào)函數(shù),就不會進(jìn)入任務(wù)隊列,也就是說,不會重新進(jìn)入主線程,因?yàn)闆]有用回調(diào)函數(shù)指定下一步的操作。

5 什么是事件循環(huán)?

JavaScript 引擎怎么知道異步任務(wù)有沒有結(jié)果,能不能進(jìn)入主線程呢?答案就是引擎在不停地檢查,一遍又一遍,只要同步任務(wù)執(zhí)行完了,引擎就會去檢查那些掛起來的異步任務(wù),是不是可以進(jìn)入主線程了。這種循環(huán)檢查的機(jī)制,就叫做事件循環(huán)(Event Loop)。

6 異步操作都有哪些模式?

  • 回調(diào)函數(shù)是異步操作最基本的方法。
    回調(diào)函數(shù)的優(yōu)點(diǎn)是簡單、容易理解和實(shí)現(xiàn),缺點(diǎn)是不利于代碼的閱讀和維護(hù),各個部分之間高度耦合(coupling),使得程序結(jié)構(gòu)混亂、流程難以追蹤(尤其是多個回調(diào)函數(shù)嵌套的情況),而且每個任務(wù)只能指定一個回調(diào)函數(shù)。
  • 另一種思路是采用事件驅(qū)動模式。異步任務(wù)的執(zhí)行不取決于代碼的順序,而取決于某個事件是否發(fā)生。
  • 事件完全可以理解成“信號”,如果存在一個“信號中心”,某個任務(wù)執(zhí)行完成,就向信號中心“發(fā)布”(publish)一個信號,其他任務(wù)可以向信號中心“訂閱”(subscribe)這個信號,從而知道什么時候自己可以開始執(zhí)行。這就叫做”發(fā)布/訂閱模式”(publish-subscribe pattern),又稱“觀察者模式”(observer pattern)。

7 什么是串行執(zhí)行和并行執(zhí)行?

  • 我們可以編寫一個流程控制函數(shù),讓它來控制異步任務(wù),一個任務(wù)完成以后,再執(zhí)行另一個。這就叫串行執(zhí)行。
  • 流程控制函數(shù)也可以是并行執(zhí)行,即所有異步任務(wù)同時執(zhí)行,等到全部完成以后,才執(zhí)行final函數(shù)。

8 如何理解觀察者模式?

事件完全可以理解成“信號”,如果存在一個“信號中心”,某個任務(wù)執(zhí)行完成,就向信號中心“發(fā)布”(publish)一個信號,其他任務(wù)可以向信號中心“訂閱”(subscribe)這個信號,從而知道什么時候自己可以開始執(zhí)行。這就叫做”發(fā)布/訂閱模式”(publish-subscribe pattern),又稱“觀察者模式”(observer pattern)。

9 JavaScript 提供定時執(zhí)行代碼功能的相關(guān)函數(shù)有哪些?

  • setTimeout函數(shù)用來指定某個函數(shù)或某段代碼,在多少毫秒之后執(zhí)行。它返回一個整數(shù),表示定時器的編號,以后可以用來取消這個定時器。
  • setInterval函數(shù)的用法與setTimeout完全一致,區(qū)別僅僅在于setInterval指定某個任務(wù)每隔一段時間就執(zhí)行一次,也就是無限次的定時執(zhí)行。
  • clearTimeout和clearInterval函數(shù),就可以取消對應(yīng)的定時器(setTimeout和setInterval)。

10 setTimeout 和 setInterval 的區(qū)別?

區(qū)別僅僅在于setInterval指定某個任務(wù)每隔一段時間就執(zhí)行一次,也就是無限次的定時執(zhí)行。

11 實(shí)現(xiàn)一個 debounce 函數(shù)?

$('textarea').on('keydown', debounce(ajaxAction, 2500));

function debounce(fn, delay){
  var timer = null; // 聲明計時器
  return function() {
    var context = this;
    var args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function () {
      fn.apply(context, args);
    }, delay);
  };
}

12 setTimeout(f, 0) 的用途有哪些?

  • 可以調(diào)整事件的發(fā)生順序。比如,網(wǎng)頁開發(fā)中,某個事件先發(fā)生在子元素,然后冒泡到父元素,即子元素的事件回調(diào)函數(shù),會早于父元素的事件回調(diào)函數(shù)觸發(fā)。如果,想讓父元素的事件回調(diào)函數(shù)先發(fā)生,就要用到setTimeout(f, 0)。
// HTML 代碼如下
// <input type="button" id="myButton" value="click">

var input = document.getElementById('myButton');

input.onclick = function A() {
  setTimeout(function B() {
    input.value +=' input';
  }, 0)
};

document.body.onclick = function C() {
  input.value += ' body'
};
  • 另一個應(yīng)用是,用戶自定義的回調(diào)函數(shù),通常在瀏覽器的默認(rèn)動作之前觸發(fā)。比如,用戶在輸入框輸入文本,keypress事件會在瀏覽器接收文本之前觸發(fā)。因此,下面的回調(diào)函數(shù)是達(dá)不到目的的。
// HTML 代碼如下
// <input type="text" id="input-box">

document.getElementById('input-box').onkeypress = function (event) {
  this.value = this.value.toUpperCase();
}
  • 另一個使用這種技巧的例子是代碼高亮的處理。如果代碼塊很大,一次性處理,可能會對性能造成很大的壓力,那么將其分成一個個小塊,一次處理一塊,比如寫成setTimeout(highlightNext, 50)的樣子,性能壓力就會減輕。

13 Promise 對象 與普通對象的區(qū)別與聯(lián)系?

14 Promise 實(shí)例具有哪三種狀態(tài)?

  • 異步操作未完成(pending)
  • 異步操作成功(fulfilled)
  • 異步操作失?。╮ejected)

15 then() 用法有哪些?

// 寫法一
// 寫法一的f3回調(diào)函數(shù)的參數(shù),是f2函數(shù)的運(yùn)行結(jié)果。
f1().then(function () {
  return f2();
});

// 寫法二
// 寫法二的f3回調(diào)函數(shù)的參數(shù)是undefined。
f1().then(function () {
  f2();
});

// 寫法三
// 寫法三的f3回調(diào)函數(shù)的參數(shù),是f2函數(shù)返回的函數(shù)的運(yùn)行結(jié)果。
f1().then(f2());

// 寫法四
// 寫法四與寫法一只有一個差別,那就是f2會接收到f1()返回的結(jié)果。
f1().then(f2);

16 Promise 的優(yōu)點(diǎn)和缺點(diǎn)?
優(yōu)點(diǎn)

  • 讓回調(diào)函數(shù)變成了規(guī)范的鏈?zhǔn)綄懛?,程序流程可以看得很清楚。它有一整套接口,可以?shí)現(xiàn)許多強(qiáng)大的功能,比如同時執(zhí)行多個異步操作,等到它們的狀態(tài)都改變以后,再執(zhí)行一個回調(diào)函數(shù);再比如,為多個回調(diào)函數(shù)中拋出的錯誤,統(tǒng)一指定處理方法等等。
  • 它的狀態(tài)一旦改變,無論何時查詢,都能得到這個狀態(tài)。這意味著,無論何時為 Promise 實(shí)例添加回調(diào)函數(shù),該函數(shù)都能正確執(zhí)行。所以,你不用擔(dān)心是否錯過了某個事件或信號。如果是傳統(tǒng)寫法,通過監(jiān)聽事件來執(zhí)行回調(diào)函數(shù),一旦錯過了事件,再添加回調(diào)函數(shù)是不會執(zhí)行的。

缺點(diǎn)

  • 編寫的難度比傳統(tǒng)寫法高,而且閱讀代碼也不是一眼可以看懂。你只會看到一堆then,必須自己在then的回調(diào)函數(shù)里面理清邏輯。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 學(xué)習(xí)教材為:https://wangdoc.com/javascript/async/index.html[htt...
    空無一碼閱讀 204評論 0 0
  • 進(jìn)程和線程的區(qū)別? 進(jìn)程是 CPU 資源分配的最小單位;線程是 CPU 調(diào)度的最小單位;一個進(jìn)程由一個或多個線程組...
    白起_syc閱讀 268評論 0 1
  • 原本想稍微整理一下 ES 新特性,沒想到花了相當(dāng)多的時間,本文也巨長,依然推薦使用 簡悅[https://gith...
    401閱讀 2,020評論 0 5
  • JavaScript高級 1.this關(guān)鍵字 this關(guān)鍵字是一個非常重要的語法點(diǎn)。毫不夸張地說,不理解它的含義,...
    smart_yang閱讀 569評論 0 1
  • 表情是什么,我認(rèn)為表情就是表現(xiàn)出來的情緒。表情可以傳達(dá)很多信息。高興了當(dāng)然就笑了,難過就哭了。兩者是相互影響密不可...
    Persistenc_6aea閱讀 129,666評論 2 7

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