3、《揭祕一線互聯網企業 前端JavaScript高級面試》視頻教程總結系列三:JS異步 相關

 


 

系列目錄:http://www.javashuo.com/article/p-mylkajzy-nt.htmlhtml

 


 

問題一:單線程是什麼?和異步有什麼聯繫?ajax

 

單線程是同一時間只作一件事,兩段js不能同時執行。json

這是由於js能夠操做Dom,爲了不兩段js同時修改一個Dom元素從而發生衝突,因此js的做者採用了單線程機制。promise

另外,由於瀏覽器的UI渲染須要渲染Dom元素,因此爲了不和js起衝突,UI渲染和js也是在同一個線程裏的;瀏覽器

其中js修改Dom的時候,UI渲染須要暫停。異步

二者單線程的實質都是爲了不Dom渲染衝突。async

 

根據單線程的原理,一件事沒作完以前程序就不往下走,這樣勢必就會致使等待,等待時間長了次數多了就會形成阻塞。模塊化

異步就是解決單線程阻塞問題的一種「無奈」的解決方案。函數

異步的原理:通俗來說,就是遇到須要等待的事件,先略過,繼續往下走同步的事件,等到到達處理異步事件的時間時,再回頭執行異步事件。oop

 

 異步致使的問題:

一、不按照書寫順序執行,可讀性很是差,不利於理解和調試;

二、callback(回調函數)嵌套層級很是多,耦合度至關高,不容易模塊化。

 


 

問題二:什麼是event-loop?什麼是異步隊列,什麼時候被放入異步隊列?

 

event-loop是事件輪詢,JS實現異步的具體解決方案。

 

event-loop執行原理:

一、全部同步任務都放在主線程中執行,造成一個執行棧;

二、遇到異步任務,暫不執行,將任務插入到異步隊列中,它是主線程外專門存放異步任務的隊列

        放入異步隊列的時機分三種狀況:

        ①沒有規定延遲時間,馬上放入異步隊列中;

        ②有延遲時間,到了延遲時間再放入異步隊列中;

        ③相似Ajax,須要等待返回的數據,什麼時候接收到數據什麼時候放入異步隊列。

三、等到主進程中的全部同步任務執行完畢時,監聽異步隊列,輪詢執行異步任務。

(輪詢是指:只要主線程空了,異步隊列中的任務就會進入執行棧,等待執行棧執行完畢,系統再去異步隊列中監聽讀取任務,讓異步任務進入執行棧,循環往復)

 


 

問題三:是否使用過Jquery的Deferred?

 

Jquery Deferred是Promise的前身,改變了異步任務必須使用回調函數來書寫的方式。

 

一、先介紹下deferred的使用實例——Jquery1.5先後Ajax寫法的變化

 

Jquery1.5以前,沒采用deferred,異步只能採用callback(回調函數)的形式,代碼都堆在一塊,沒法模塊化,不便於擴展(對修改開放、對擴展封閉)。

var ajax = $.ajax({ url:'data.json', success:function () { console.log('success 1'); console.log('success 2'); console.log('success 3'); }, error:function () { console.log('error'); } }); console.log(ajax); // 返回一個XHR對象

 

Jquery1.5以後,採用了deferred,deferred對象調用的第一種寫法,異步能夠採用鏈式調用,done、fail兩個函數成對出現,將異步函數按照同步的邏輯書寫與執行,代碼實現了模塊化。

var ajax = $.ajax('data.json'); ajax.done(function () { console.log('success 1'); }) .fail(function () { console.log('error 1'); }) .done(function () { console.log('success 2'); }) .fail(function () { console.log('error 2'); }) .done(function () { console.log('success 3'); }) .fail(function () { console.log('error 3'); }) console.log(ajax); // 返回一個deferred對象

 

Jquery1.5後採用deferred,調用的第二種寫法,也是鏈式調用,函數和容錯函數都包含在了then裏面,已經至關接近ES6中的Promise了。

var ajax = $.ajax('data.json'); ajax.then(function() { console.log('success 1'); }, function() { console.log('error 1'); }) .then(function() { console.log('success 2'); }, function() { console.log('error 2'); }) .then(function() { console.log('success 3'); }, function() { console.log('error 3'); })

 Jquery1.5以後Ajax的寫法,體現了五大設計原則中的開放封閉原則(對修改封閉、對擴展開放),更加方便開發人員的修改、擴展與協同開發。

它以一種語法糖的形式解耦了代碼,是從寫法上杜絕了callback這種形式,並不能改變js單線程和異步的本質。

 

二、介紹Jquery Deferred 的具體用法,封裝一個deferred(很是相似於封裝Promise)

 

原始代碼及需求

// setTimeout模擬異步
var wait = function() { var task = function() { console.log('打印一') } setTimeout(task, 2000); } wait() // 需求爲,在'打印一'後每一個2秒分別打印'打印二','打印三'

 

 使用Jquery的deferred,將函數封裝以後

function waitHandle() { var dtd = $.Deferred(); // 建立一個deferred對象
    
    return wait = function (dtd) { // 傳入deferred對象,並做爲promise對象返回
        var task = function () { console.log('打印一') dtd.resolve() // 表示異步任務已完成
 } setTimeout(task, 2000); return dtd.promise() // 要求返回promise對象,防止外部調用dtd.resolve()或dtd.reject()阻止進程
 } }

 

調用封裝好的deferred方法,這裏用的是then,另外一種寫法還能夠將一個then()替換成一對的done(),fail()

var w = waitHandle() w.then(function() { console.log('打印二') }) .then(function() { console.log('打印三') })

以上即是deferred的用法。

 

整體回答彙總:

Jquery Deferred是Promise的前身,改變了異步任務必須使用回調函數來書寫的方式。

使用deferred後,能夠將異步函數按照同步的邏輯書寫與執行,代碼實現了簡單的模塊化。

Jquery1.5以後Ajax的寫法使用了deferred,能夠鏈式調用,體現了五大設計原則中的開放封閉原則(對修改封閉、對擴展開放),更加方便開發人員的修改、擴展與協同開發。

它以一種語法糖的形式解耦了代碼,雖然從寫法上杜絕了callback這種形式,但並無改變js單線程和異步的本質。

 

deferred有兩類API:

第一類是dtd.resolve()、dtd.reject(),這類是主動觸發的方法;

第二類是dtd.then()或dtd.done()、dtd.fail(),這一類是被動接受的方法;

兩類方法不能夠在一塊兒混用,不然會形成程序混亂。

因此爲了不這一問題,在封裝deferred的時候,最終返回的應該是dtd.promise(),

這樣就過濾掉了dtd.resolve()和dtd.reject(),使外部沒法調用deferred對象的resolve()、reject()。

 


 

問題四:Promise的基本使用和原理。

 

一、基本語法

    ①封裝:

        ——new 一個Promise對象,傳入一個函數,函數有兩個參數,分別是resolve()和reject()方法;

        ——在Promise對象內部書寫具體邏輯,成功則resolve(), 失敗則reject ();

        ——最後返回new出來的這個Promise對象。

    ②調用:使用.then()鏈式調用,then接收兩個函數,一個是成功函數,一個是失敗函數。

    (如下我就偷個懶不放代碼,直接放截圖辣)

    

 

二、異常捕獲

    每一個then都接收兩個函數比較麻煩,使用異常捕獲就方便許多,

    異常捕獲規定then只接受一個參數,最後統一用catch捕獲異常。

    catch能夠捕獲兩種錯誤,一種是邏輯以外的錯誤(語法報錯),一種是邏輯內的錯誤(reject拋出的錯誤)。

    

 

 

三、多個串聯

    在前一個then中返回一個Promise對象,下一個then接收參數的就是上一個Promise對象resolve出來的結果。

    

 

下班啦,未完待續。。。

 

四、Promise.all() 、Promise.race()

五、Promise的標準

 


 

問題五:介紹一下async/await(和Promise的區別和聯繫)

相關文章
相關標籤/搜索