js回調的心酸歷程

項目代碼

demo準備的啰嗦了,如果你同我一樣是個急性子,可以直接忽略

捂臉

需求

demo中src文件里有a、b、c三個json文件,需求是我們需要依次請求它們,并且打印它們的值。

發展史

  • ES5 - 金字塔
  • ES6 - 鏈式
  • ES6 - 暫停
  • ES7 - 同步

ES5 - 金字塔

首先我們來到ES5的時代,為完成以上的需求寫下如下的代碼:

  $.ajax('./src/a.json').done((a)=>{

        console.log(a.data) // 打印a文件

        $.ajax('./src/a.json').done((b)=>{

              console.log(b.data)  // 打印b文件

              $.ajax('./src/a.json').done((c)=>{
                       console.log(c.data)  // 打印c文件
              })
        })
  })
  

嗯,也不錯啊,一層套著一層,也算清晰明了了。如果當我們的需要改成100個文件的依次獲取呢?此時,如果還這樣寫的話,那歡迎你來到回調地獄

如果我們嵌套很多的代碼,像金字塔一樣的堆疊起來,不僅僅讓代碼顯得更加難看、臃腫,也讓項目變得越來越不好維護。

ES6 - 鏈式

我們來到了ES6的時代,這個時代的有個產物叫做promise

通過promise我們可以將代碼鏈式的調用?改成??如下的代碼

function request(url){
    return new Promise((resolve, reject)=>{
        $.ajax(url).done((data)=>{
            resolve(data)
        }).fail((err)=>{
            reject(err)
        })
    })
}

request('./src/a.json').then((a)=>{
    console.log(a)
    return request('./src/b.json')
}).then((b)=>{
    console.log(b)
    return request('./src/c.json')
}).thne((c)=>{
    console.log(c)
})

相比金字塔式嵌套的代碼,此時的代碼更加的簡潔,也更容易維護,但是也只不過是將嵌套改成了上下鏈接調用。

ES6 - 暫停

Generator 函數是 ES6 提供的一種異步編程解決方案,可以理解成內部有很多狀態的狀態機。

generator函數與普通函數區別:

  • 定義的時候多了個*
  • 函數內部使用yield來定義不同的狀態
  • 調用的時候,需要將函數賦值給某個變量,每個變量之間的狀態互不影響
  • 使用next()函數調用下一個狀態
function request(url){
    $.ajax(url).done((data)=>{
        generator.next(data)
    })
}


function* generatorFn(){
    let a = yield request('./src/a.json')
    console.log(a)
    let b = yield request('./src/b.json')
    console.log(b)
    let c = yield request('./src/c.json')
    console.log(c)
}

var generator = generatorFn()

generator.next()

以上代碼定義了generatorFn函數并賦值給generator,在定義request函數的時候,當請求到數據的時候,調用generator的next方法。

ES7 async/await

萬眾矚目,神器登場 async/await

先上代碼:

(async () => {
    let a = await $.ajax('./src/a.json')
    console.log(a)
    let b = await $.ajax('./src/b.json')
    console.log(b)
    let c = await $.ajax('./src/c.json')
    console.log(c)
})

async函數是generator函數的語法糖,只是將*變成了async,yield改成了await,但是代碼卻精簡了這么多,它們直接的區別有以下幾點:

  • async函數不用手動去調用next() 函數
  • async函數返回值是promise,generator函數返回的是Iterator

async函數可以看成一個包含多個異步操作的promise的對象,await就是then的語法糖。

四種方式中最精簡的方式。使用async處理回調函數,代碼會異常的清新,我們寫起來也會很爽很舒服。

為什么會有這種感覺呢?

因為它是最符合我們寫代碼的習慣,用同步的寫法去解決異步的代碼。

參考文檔:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容