原文首發地址:http://www.cnblogs.com/lonhon/p/7518231.html
先簡單介紹下async await:
async/await是ES6推出的異步處理方案,目的也很明確:更好的實現異步編程。 詳細見阮大神 ES6入門
現在說說實踐中遇到的問題:使用await報錯Unexpected identifier
先上代碼:
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函數,代碼如下:
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();
運行結果:
至此,問題解決。
a
wait
必須在async函數的上下文中。出處
上下文,英文context,其完整意思應當是concatenate-text,聯系文本,編程中翻譯為“引用池”或者“引用區”更加恰當
先舉個例子:
③.小明說:重啟試試
單從這句話我們不能知道重啟什么、為什么小明要說這句話(可能你覺得是電腦)、對誰說的這句話
②.小紅說對小明說她微信出來不了輸入法
這就是小明為什么說這句話的上文(背景),這時候才能知道小明說的重啟是微信程序or手機(真不是電腦)
①.小紅和小明躺在床上玩手機
這句也是背景,但是卻不能成為3的上文,因為“躺床上”並不是“重啟試試”的原因(或者說背景)
函數調用會在內存形成一個"調用記錄",又稱"調用幀"(call frame),保存調用位置和內部變量等信息
個人理解:上文指出了環境、背景。
拿本文中的第一段錯誤代碼來說,await的上文是一個普通箭頭函數,所以使用await會報錯,因為編譯器在執行到await時,當前調用幀是箭頭函數而不是外層的start,所以此時的await就像:小明和小紅躺在床上 小明說“重啟試試” ,是無意義(Unexpected identifier)的。
這時候談談下文,接上面的例子
④.小紅重啟了手機
這時候④就是③的下文
需要注意的是,上下文是一個整體,上面我把它分開只是為了理解,實際過程中,不存在單獨的上文和下文,所以這是await 必須在async 的上下文 的具體意義。