1. 程式人生 > 實用技巧 >JavaScript——promise 是解決非同步問題的方法嘛

JavaScript——promise 是解決非同步問題的方法嘛

前言

  • promise
  • 非同步解決方案

步驟

Promise 物件是 JavaScript 的非同步操作解決方案,為非同步操作提供統一介面。它起到代理作用(proxy),充當非同步操作與回撥函式之間的中介,使得非同步操作具備同步操作的介面。Promise 可以讓非同步操作寫起來,就像在寫同步操作的流程,而不必一層層地巢狀回撥函式。

Promise解決了callback回撥地獄的問題,async、await 是非同步的終極解決方案。

來看一下JavaScript中非同步方案

1)回撥函式(callback)

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

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

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

  • 缺乏順序性: 回撥地獄導致的除錯困難,和大腦的思維方式不符
  • 巢狀函式存在耦合性,一旦有所改動,就會牽一髮而動全身,即(控制反轉)
  • 巢狀函式過多的多話,很難處理錯誤
ajax('XXX1', () => {
    // callback 函式體
    ajax('XXX2', () => {
        // callback 函式體
        ajax('XXX3', () => {
            // callback 函式體
        })
    })
})

優點: 解決了同步的問題(只要有一個任務耗時很長,後面的任務都必須排隊等著,會拖延整個程式的執行。)

2)Promise

Promise就是為了解決callback的問題而產生的。Promise 實現了鏈式呼叫,也就是說每次 then 後返回的都是一個全新 Promise,如果我們在 then 中 return ,return 的結果會被 Promise.resolve() 包裝

優點: 解決了回撥地獄的問題

ajax('XXX1')
  .then(res => {
      // 操作邏輯
      return ajax('XXX2')
  }).then(res => {
      // 操作邏輯
      return ajax('XXX3')
  }).then(res => {
      // 操作邏輯
  })

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

3)Generator

特點: 可以控制函式的執行,可以配合 co 函式庫使用

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

async、await 是非同步的終極解決方案

優點: 程式碼清晰,不用像 Promise 寫一大堆 then 鏈,處理了回撥地獄的問題

缺點: await 將非同步程式碼改造成同步程式碼,如果多個非同步操作沒有依賴性而使用 await 會導致效能上的降低。

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