Javascript高級面試

原型

異步

一、什麼是單線程,和異步有什麼關係

單線程:只有一個線程,同一時間只能做一件事

原因:避免DOM渲染的衝突
解決方案:異步

爲什麼js只有一個線程:避免DOM渲染衝突
  • 瀏覽器需要渲染DOM
  • JS可以修改DOM結構
  • JS執行的時候,瀏覽器DOM渲染會暫停
  • 兩端JS也不能同時執行(都修改DOM就衝突了)
  • webworker支持多線程,但是不能訪問DOM

 

解決方案存在的問題
  • 問題一:沒按照書寫方式執行,可讀性差
  • 問題二:callback中不容易模塊化

二、什麼是event-loop

  • 事件輪詢,JS實現異步的具體解決方案
  • 同步代碼,直接執行
  • 異步函數先放在異步隊列中
  • 待同步函數執行完畢,輪詢執行異步隊列的函數
setTimeout(function(){
    console.log(1);
},100);              //100ms之後才放入異步隊列中,目前異步隊列是空的
setTimeout(function(){
    console.log(2);  //直接放入異步隊列
})
console.log(3)       //直接執行

//執行3之後,異步隊列中只有2,把2拿到主線程執行,2執行完之後,異步隊列中並沒有任務,所以一直輪詢異步隊列,直到100ms之後1放入異步隊列,將1拿到主線程中執行
$.ajax({
    url:'./data.json',
    success:function(){        //網絡請求成功就把success放入異步隊列
        console.log('a');
    }
})

setTimeout(function(){
    console.log('b')
},100)

setTimeout(function(){
    console.log('c');
})
console.log('d')

//打印結果:
//d    //d   
//c    //c  
//a    //b   
//b    //a   

//真實環境不會出現dacb

三、是否用過jQuery的Deferred

  • jQuery1.5的變化
  • 使用jQuery Deferred
  • 初步引入Promise概念

 

jQuery1.5之前
var ajax = $.ajax({
    url:'./data.json',
    success:function(){
        console.log('success1');
        console.log('success2');
        console.log('success3');
    },
    error:function(){
        console.log('error');
    }
})
console.log(ajax); //返回一個XHR對象

 

jQuery1.5之後
var ajax = $.ajax('./data.json');
ajax.done(function(){
    console.log('success1')
})
.fai(function(){
    console.log('fail')
})
.done(function(){
    console.log('success2');
})
console.log(ajax); //deferred對象
var ajax = $.ajax('./data.json');
ajax.then(function(){
    console.log('success1')
},function(){
    console.log('error1');
})
.then(function(){
    console.log('success2');
},function(){
    console.log('error');
})

//使用
var w = waithandle()
w.then(function(){
    console.log('ok1');
},function(){
    console.log('err2');
})
.then(function(){
    console.log('ok2');
},function(){
    console.log('err2');
})
//還有w.wait w.fail
  • 無法改變JS異步和單線程的本質
  • 只能從寫法上杜絕callback這種形式
  • 它是一種語法糖,但是解耦了代碼
  • 很好的提現:開放封閉原則(對擴展開放對修改封閉)
使用jQuery Deferred
//給出一段非常簡單的代碼,使用setTimeout函數
var wait = function(){
    var task = function(){
        console.log('執行完成');
    }
    setTimeout(task,2000)
}

wait();

//新增需求:要在執行完成之後進行某些特別複雜的操作,代碼可能會很多,而且分好幾個步驟
function waitHandle(){
    var dtd = $.Deferred();//創建一個deferred對象
    
    var wait = function(dtd){  // 要求傳入一個deferred對象
        var task = function(){
            console.log("執行完成");
            dtd.resolve();  //表示異步任務已完成
            //dtd.reject() // 表示異步任務失敗或者出錯
        };
        setTimeout(task,2000);
        return dtd;
    }
    //注意,這裏已經要有返回值
    return wait(dtd);
}
/*
*總結:dtd的API可分成兩類,用意不同
*第一類:dtd.resolve  dtd.reject
*第二類:dtd.then  dtd.done  dtd.fail

*這兩類應該分開,否則後果嚴重!
*可以在上面代碼中最後執行dtd.reject()試一下後果
*/
使用dtd.promise()
function waitHandle(){
    var dtd = $.Deferred();
    var wait = function(){
        var task = function(){
            console.log('執行完成');
            dtd.resolve();
        }
        setTimeout(task,2000)
        return dtd.promise();  //注意這裏返回的是promise,而不是直接返回deferred對象
    }
    return wait(dtd)
}


var w = waitHandle();   //promise對象
$.when(w).then(function(){
    console.log('ok1');
},function(){
    console.log('err1');
})
/*
只能被動監聽,不能干預promise的成功和失敗
*/
  • 可以jQuery1.5對ajax的改變舉例
  • 說明如何簡單的封裝、使用deferred
  • 說明promise和Defrred的區別

要想深入瞭解它,就需要知道它的前世今生

四、Promise的基本使用和原理

基本語法回顧
異常捕獲

//規定:then只接受一個函數,最後統一用catch捕獲異常

多個串聯
var scr1 = 'https://www.imooc.com/static/img/index/logo_new.png';
var result1 = loadImg(src1);
var src2 = 'https://www.imooc.com/static/img/index/logo_new.png';
var result2 = loadImg(src2);

result1.then(function(img1) {
    console.log('第一個圖片加載完成', img1.width);
    return result2;
}).then(function(img2) {
    console.log('第二個圖片加載完成', img2.width);
}).catch(function(ex) {
    console.log(ex);
})
Promise.all和Promise.race
//Promise.all接收一個promise對象的數組
//待全部完成後,統一執行success
Promise.all([result1, result2]).then(datas => {
        //接收到的datas是一個數組,依次包含了多個promise返回的內容
        console.log(datas[0]);
        console.log(datas[1]);
})
   
//Promise.race接收一個包含多個promise對象的數組
//只要有一個完成,就執行success
Promise.race([result1, result2]).then(data => {
    //data即最先執行完成的promise的返回值
    console.log(data);
})
Promise標準
  • 三種狀態:pending,fulfilled,rejected
  • 初始狀態:pending
  • pending變爲fulfilled,或者pending變爲rejected
  • 狀態變化不可逆

promise必須實現then這個方法
then()必須接收兩個函數作爲標準
then

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

六、總結一下當前JS結局異步的方案

虛擬DOM

MVVM和vue

組件化和React

hybrid

未完待續,每日更新

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章