JS 異步解決方案的發展歷程解析

1.回調函數(callback)

setTimeout(() => {
    // callback 函數體
}, 1000)

缺點:回調地獄,不能用try catch 捕獲錯誤,不能return

 try {
        setTimeout(() => {
            console.log(aa)
        }, 1000)
    } catch (error) {
        
}
//報錯:Uncaught ReferenceError: aa is not defined

回調地獄的根本問題在於:

  • 缺乏順序性: 回調地獄導致的調試困難,和大腦的思維方式不符
  • 嵌套函數存在耦合性,一旦有所改動,就會牽一髮而動全身,即(控制反轉)
  • 嵌套函數過多的多話,很難處理錯誤
function a(functionb(){
    c(function d(){
    
    })
})

如何解決回調地獄?(看下面的方法)

2.Promise(ES6)

  • Promise有三種狀態:pending/reslove/reject 。pending就是未決,resolve可以理解爲成功,reject可以理解爲拒絕。
  • 同時Promise常用的三種方法 then 表示異步成功執行後的數據狀態變爲reslove catch 表示異步失敗後執行的數據狀態變爲reject all表示把多個沒有關係的Promise封裝成一個Promise對象使用then返回一個數組數據。
function f(){
    let promise = new Promise((resolve, reject) => {
        //模擬異步
        setTimeout(()=>{
            resolve('prom')
        },1000)
        
    })
    return promise
}
function f1() {
 //返回一個Promise用於下一次調用then
     return f().then(data=>{
     // 返回的數據用於下一次then使用
         return data+'ise'
     })
 }
f1().then(data=>{
     console.log(data)
})
 console.log("hello word")	
 結果: hello word
promise

寫成鏈式結構如下

new Promise((resolve, reject) => {
        //模擬異步
        setTimeout(()=>{
            resolve('prom')
        },1000)
        
    }).then(data=>{
        return data+'ise'
    }).then(data=>{
        console.log(data)
    })

缺點:無法取消 Promise ,錯誤需要通過回調函數來捕獲

3.Generator(生成器,es6)

  • Generator(生成器)是一種有效利用內存的機制,一邊循環一邊計算生成數值的機制。通過配合Promise可以更加優雅的寫異步代碼
    特點 : 可以控制函數的執行
function *fetch() {
    yield ajax('XXX1', () => {})
    yield ajax('XXX2', () => {})
    yield ajax('XXX3', () => {})
}
let it = fetch()
let result1 = it.next()
let result2 = it.next()
let result3 = it.next()

缺點:生成器不是最完美的,它的語法讓人難以理解

4.Async/await (異步等待, es7)

async、await 是異步的終極解決方案
優點:代碼清晰,不用像 Promise 寫一大堆 then 鏈,處理了回調地獄的問題
缺點:await 將異步代碼改造成同步代碼,如果多個異步操作沒有依賴性而使用 await 會導致性能上的降低。
函數前面加async 表示該函數是一個異步函數 await 表示等待一個異步值的到來
eg1

async function test() {
  // 以下代碼沒有依賴性的話,完全可以使用 Promise.all 的方式
  // 如果有依賴性的話,其實就是解決回調地獄的例子了
  await fetch('XXX1')
  await fetch('XXX2')
  await fetch('XXX3')
}

異步函數可以更加方便的同Promise結合使用來書寫同步代碼風格的異步執行
eg2:

function f() {
    return new Promise((resolve, reject) => {
        setTimeout(()=>{
            resolve("hello word")
        },1000)
    })
}
async function a(){
   var data = await f();
   return data;
}
a().then(data=>{
    console.log(data)
})
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章