【 JS進階 ]】分析JS中的異步操做

  JS由於是單線程的,因此在執行事務的時候,每每會由於某個事務的延遲,而致使服務器假死,這時候異步編程就顯的格外重要,可是異步編程通常理解爲回調函數callback,典型的就是node,回調函數的層層嵌套又致使程序過於冗餘,由於閉包的存在,致使了內存的泄露或者誤改上一層回調函數的參數,因而又有一個疑問,能不能用同步的方式去寫異步,ES6的promise就是以同步流程的方式寫出異步操作,可是piomise原生操做寫起來比較長,能不能簡介操做promise,ES7就又出現async/await的概念,與async/await同等語法糖做用的有依賴co庫的generator函數,generator函數也是用來解決異步操做,不過得依賴co庫,co 函數庫是著名程序員 TJ Holowaychuk 於2013年6月發佈的一個小工具,用於generator函數的自動執行。前端

  好了,那就羅列出js的異步操做node

  一、回調函數git

 

    ajax典型的異步操做,利用XMLHttpRequest,回調函數獲取服務器的數據傳給前臺  程序員

    以前也分析過ajaxgithub

    回調函數的含義就是耗時任務f1中執行f2,f1不會堵塞住,而是先執行f2,再延遲執行f1web

  二、事件監聽ajax

 

    addEventListener編程

    當監聽事件發生時,先執行回調函數,再對監聽事件進行改寫json

  三、觀察者模式,也叫訂閱發佈模式promise

 

    多個觀察者能夠訂閱同一個主題,主題對象改變時,主題對象就會通知這個觀察者

    其中步驟包括,訂閱、發佈、退訂;先訂閱(subscribe)一個主題對象,根據主題對象發佈(publish)內容,期間也退訂(unsubscribe)主題對象,一旦退訂就沒法再次發佈

    能夠把訂閱一個主題對象理解成監聽一個事件

    觀察者模式的一個特色就是一旦主題事件一改變,就會通知整個觀察者;觀察者模式還能夠計算出訂閱事件的個數

  四、promise

 

    上面也提到了,promise是異步編程的解決方案,是一種容器,保存着異步操做的結果,能夠把異步函數以同步函數的形式寫出來

    promise第一個特色:對象狀態不受外界影響,有三個狀態pending(),fulfilled(),rejected(),只有異步操做纔會更改這個狀態,其餘操做沒法改變這個狀態

    promise第二個特色:一旦狀態改變,pending->fulfilled或pending->rejected,狀態就會凝固住,稱爲resolve,經過promise的回調函數能夠當即獲得這個結果,與事件監聽不一樣,一旦事件錯誤,就沒法再次監聽

    promise第三個特色:避免了回調函數的層層嵌套,實際上寫promise時,雖然沒有回到函數的層層嵌套,可是又有then的嵌套,這個又有新的解決方法

    promise第一個缺點:一旦promise創建,就會當即執行,沒法中途中止

      舉個例子,假如去淘寶買東西,去看上一個東西,想要買,已經點擊肯定購買了,可是你又cancle了,忽然你發現工資發了,你又發送一個請求說又要買了,服務器接收到了你的第一個異步請求,你又有異步請求,異步請求又不能中止,求服務器陰影面積?

    promise的第二個缺點:promise不設置回調函數,拋出的錯誤沒法在外部捕獲

    piomise的第三個缺點:處於pending狀態,沒法知道進展到哪一個狀態

    下面一個經典的案例:用promise寫出ajax,就體現了promise的特色

 

             function getJSON(url){

                varpromise = new Promise(function(resolve,reject){

                var xhr=  newXMLHttpRequest();

                xhr.open("get",url);

                xhr.onreadystatechange=ajax;

                xhr.responseType ="json";

                xhr.setRequestHeader("Accept","application/json");

                xhr.send();

                functionajax(response){

                    if (this.readyState !=4) {

                        return;

                    }

                    if (this.status ==200) {

                            resolve(this.response)

                    }else{

                        reject(new Error(this.status.responseText))

                    }

                  

                }

            })

            returnpromise;

        }

        getJSON("/new2").then(function(value){

            console.log(value);

        },function(error){

            console.log(error);

        })

 

   五、es7語法糖async/await

 

     async異步函數是promise的完成狀態,async函數直接then去獲取狀態改變值,catch來獲取錯誤

     await只容許在async內部使用,就是async異步函數內部想要繼續then,就能夠採用await異步函數,await異步函數是內部的async異步函數

       async極大精簡了promise的操做   

async  function asyncFn(){

        return 123;

    }

    asyncFn()

        .then(x => {console.log(x)})

        .catch(err=> console.log(error))

 

    這是未精簡的promise操做,功能是把最終結果return最外層的promise,可是 用到了多層嵌套,比較複雜

 

    const fn = () => {

        returngetJSON()

            .then(data =>{

                if(data.params){

                    returnotherGetJSON(data).then(otherdata =>{

                        console.log(otherdata);

                        return otherdata;

                    })

                }else{

                    console.log(data)

                }

            })

    }

 

    而async異步函數,直接去return出結果就行,這就是await是async內部async異步函數

 

    const fn = async () => {

        const data = await getJSON();

        if(data.params){

            const otherdata = awaitotherGetJSON(data);

            console.log(otherdata);

            returnotherdata;

        }else{

            console.log(data)

            return data;

        }

    }

 

    六、co庫的generator函數

 

      generator函數是一個異步函數,只有異步操做有結果纔會交還執行權

      generator用到了ES6的遍歷Iterator的概念,建立一個指針對象,指向數據結構的起始位置,每次next指向下一個指針結構成員,直至指向的下一個結構成員爲undefined

      generator概念就是,每次遍歷讀用next方法,內部指針從結構頭部指向下一個結構成員,直至下一個結構成員爲undefined,遇到yield或return時會返回value和done參數,value表示yield或return的值,done表示是否結束 

 

function * gen(x){

      var y = yield x +2;  

   

      return y;

}

var g = gen(1);

console.log(g.next())// { value: 3, done: false }

console.log(g.next())// { value: undefined, done: true }

 

      yield是遍歷的中止標誌

      而generator中的yield*表示 yield* 後面跟着一個可遍歷的結構

須要瞭解web前端的同窗,+羣434/6239/99

相關文章
相關標籤/搜索