先簡單介紹下async await:html
async/await是ES6推出的異步處理方案,目的也很明確:更好的實現異步編程。 詳細見阮大神 ES6入門node
如今說說實踐中遇到的問題:使用await報錯Unexpected identifieres6
先上代碼:編程
var sleep = function (time) { return new Promise(function (resolve, reject) { setTimeout(function () { resolve(('999')); }, time); }) }; let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] var start = async function(){ arr.forEach(()=>{ console.log( await sleep(2000) ) }) } start();
在循環中使用sleep方法,這時候報錯:Unexpected identifier微信
緣由:經過查資料發現一句話 await必須在async函數的上下文中。(後面重點講)經過我的理解的這句話就是await只能在async函數中使用。異步
以上面的代碼爲例子,雖然最外層start函數是經過async聲明的,在start函數體內部的箭頭函數中使用了await,而該箭頭函數是一個普通函數,因此await的上文是一個普通函數,最終致使報錯。async
解決辦法,將箭頭函數聲明爲async函數,代碼以下:ide
var sleep = function (time) { return new Promise(function (resolve, reject) { setTimeout(function () { resolve(console.log('999')); }, time); }) }; let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] var start = function(){ arr.forEach(async ()=>{ await sleep(2000) }) } start();
運行結果:異步編程
至此,問題解決。函數
await必須在async函數的上下文中。----出處
上下文,英文context,其完整意思應當是concatenate-text,聯繫文本,編程中翻譯爲「引用池」或者「引用區」更加恰當。----百度百科
先舉個例子:
③.小明說:重啓試試
單從這句話咱們不能知道重啓什麼、爲何小明要說這句話(可能你以爲是電腦)、對誰說的這句話
②.小紅說對小明說她微信出來不了輸入法
這就是小明爲何說這句話的上文(背景),這時候才能知道小明說的重啓是微信程序or手機(真不是電腦)
①.小紅和小明躺在牀上玩手機
這句也是背景,可是卻不能成爲③的上文,由於「躺牀上」並非「重啓試試」的緣由(或者說背景)
函數調用會在內存造成一個"調用記錄",又稱"調用幀"(call frame),保存調用位置和內部變量等信息
我的理解:上文指出了環境、背景。
拿本文中的第一段錯誤代碼來講,await的上文是一個普通箭頭函數,因此使用await會報錯,由於編譯器在執行到await時,當前調用幀是箭頭函數而不是外層的start,因此此時的await就像:小明和小紅躺在牀上 小明說「重啓試試」 ,是無心義(Unexpected identifier)的。
這時候談談下文,接上面的例子
④.小紅重啓了手機
④就是③的下文
上下文結合在一塊兒才能構建一個完整的邏輯
好比④和③就是上下文,咱們才能將其聯繫起來,若是隻有④或者④和②,從邏輯上來講都不是完整的。
對程序而言 有了上下文「調用幀」纔有一個完整的邏輯過程。計算機才知道下一步該去哪,該回到哪。
須要注意的是,上下文是一個總體,上面將其分開只是爲了理解,實際過程當中,不存在單獨的上文和下文,因此這是await 必須在async 的上下文 的具體意義。