先简单介绍下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 的上下文 的具体意义。