1. 程式人生 > >解決js非同步問題的方法--async和await(ES7)

解決js非同步問題的方法--async和await(ES7)

非同步在給我們解決阻塞的問題時也帶來一些別的問題
開發中呼叫介面經常是非同步的,然後不小心就會犯的錯誤就是介面的資料還沒有返回,我們就當作它已經返回了,然後繼續處理,當然就會發生錯誤。
為了避免資料還沒返回就繼續執行,我們一般會在回掉函式裡面繼續些,但當層次多的時候不免會越來越亂,可讀性別差
ES6引入promise函式處理非同步問題,比之前好多了,但也並沒有達到像寫同步一樣,ES7的兩個新東西解決了這個問題,是我們像書寫同步程式碼一樣。
ES6-阮一峰:http://es6.ruanyifeng.com/#docs/promise (不懂promise的可以先看一下)

下面我會用我的理解,和容易讓你明白的通俗的白話(其實是專業的也不會0.0)說明介紹一下async函式和await關鍵詞(操作符)

async

如果你要寫一個函式,裡面包含有非同步呼叫的函式,那麼請你在定義這個函式之前加上async關鍵詞

async function f1 () {
  let x = await resolveAfter2Second(10)
  console.log(x)
}

上面的resolveAfter2Second(10)是一個非同步函式(promise 物件寫的 一會具體解釋)
像這個一樣 如果內部用非同步函式 就在宣告函式的時候用async關鍵字

await

await 操作符用於等待一個Promise 物件

await的作用就是等回撥有了結果之後在執行下面的程式

看個例子

function resolveAfter2Second (x, time) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x)
    },time)
  })
}
async function f1 () {
  let x = await resolveAfter2Second(10, 2000)
  console.log(x)
}
f1()

解讀一下:
resolveAfter2Second()用setTimeout模擬一個非同步請求,然後回撥
如果沒有async 和 await f1()函式會在等待resolveAfter2Second()時先執行console.log(x) 這是並不時我們想得到的
因為加了await 會 在resolveAfter2Second()函式有了返回結果後在執行下面的內容
所以看起來書寫的方式和正常同步一樣

function resolveAfter2Second (x, time) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x)
    }, time)
  })
}
let add1 = async function (x) {
  let a = resolveAfter2Second(20, 2000)
  let b = resolveAfter2Second(30, 5000)
  return x + await a + await b
}
add1(10).then(res => {
  console.log('add1111', res)
})
let add2 = async function (y) {
  let a = await resolveAfter2Second(20, 2000)
  let b = await resolveAfter2Second(30, 5000)
  return y + a + b
}
add2(100).then(res => {
  console.log('add22222', res)
})

看一下這個例子:
區別就是 await 寫的位置不同,這會造成add1在5秒之後彈出結果,而add2會在7秒之後
add2 的 await寫在resolveAfter2Second()前面,會在得到結果之後在執行下面的,所以是2S+5S,而add1的await寫在a和b兩個結果之前,是在a b得到值後在執行加法。

let a = resolveAfter2Second(20, 2000)
let b = resolveAfter2Second(30, 5000)

他們會像正常非同步一樣同時執行,所以只需要5s, 所以add1這種寫法還是存在問題的

let b = resolveAfter2Second(30, 5000)
let a = resolveAfter2Second(20, 2000)

如果b的結果對a有影響b的用時較長,因此a的執行結果就有可能不正確,就和非同步的問題一樣。

總之就是加上async和await之後你就可以已正常方式書寫了,不過因為必須會等待回撥的結果 所以又可能會有等待(阻塞)的問題(沒實際中使用,可能或許不會,如果錯誤請各位及時提醒,謝謝了)

還有一個問題就是這個是ES7的內容瀏覽器的相容不是很好,現在chrome firefox opera都可以,但蘋果的safari還不行,所以適當使用吧