ES7 Async/Await 陷阱

什么是Async/Await

ES6新增了Promise函数用于简化项目代码流程。然而在使用promise时,我们仍然要使用callback,并且并不知道程序要干什么,例如:

function doSomething() {
    let i = 0;
    waitOneSecond() // 返回一个Promise对象
        .then(() => console.log(i));
    i = 5;
}

最终console.log(i) 的结果是5,并不是0

为此,ES7引入了async函数,前面的例子可以改写这样:

async function doSomething() {
    let i = 0;
    await waitOneSecond();// 等待1秒
    console.log(i);
    i = 5;
}

这段代码片段中console.log(i)的结果是0。其中关键字await停止当前函数的执行,直到waitOneSecond()返回的promise对象状态变更为fulfilled(完成),并产生其返回值。

当返回的promise对象的状态变更为rejected(失败),错误信息会被 try/catch 代码块所捕获。

常见陷阱

效率损失:

乱用async/await,可能导致低效的设计模式。例如,假设我们想从数据库中获得一些用户他们的年龄平均。我们会这样做的:

async function getUserAge(userId) {
    await waitOneSecond();// 等待1秒
    return 7;
}
async function getAverageAge(userIds) {
    let sumOfAges = 0;
    let numOfUsers = userIds.length;
    for (let userId of userIds) {
        sumOfAges += await getUserAge(userId);
    }
    return sumOfAges / numOfUsers;
}

显而易见,这是错误的,假设我们有5个用户,上面的代码片段会轮训所有的用户并且等待每一个单独调用数据库,所以最终整个函数的等待时间是5秒。

为了更好的性能,降低等待时间,修改如下:

async function getAverageAge(userIds) {
    let sumOfAges = 0;
    let numOfUsers = userIds.length;
    let agesPromises = userIds.map(getUserAge);//将每个用户对应的promise对象封装到数组中
    let ages = await Promise.all(agesPromises);//使用Promise.all调用
    for (let age of ages) {
        sumOfAges += age;
    }
    return sumOfAges / numOfUsers;
}

修改之后,代码变得复杂了一些,但是所有的数据库调用,都是同时进行的。无论你有多少用户,这个方法的等待时间只需要1秒。

在使用async/await函数时,当函数体内需要使用await多次调用外部函数并且函数返回值彼此无依赖关系时,使用Promise.all降低函数整体的等待时间。

变量污染:

当使用async函数时,会令代码更易阅读,但是他们并不是真正的将你的代码变为同步,只是promise的语法糖而已,看下面这个例子

let currentUserId = 0;
async function getInfoAboutUser() {
    currentUserId++; // 令每个用户id均唯一
    let data = await waitTenSeconds(); // 获取某些其他数据,等待时间10秒
    return { id: currentUserId , data };
}
async function registerUser() {
    let user = await getInfoAboutUser();
    await storeUser(user);
}

现在假设,有2个不同的用户接连注册,getInfoAboutUser 函数将被接连执行,当10秒的等待时间结束后,2个用户的id都是相同的。

在这个例子中,我们可以很简单的避免这个问题:

async function getInfoAboutUser() {
    let data = await waitTenSeconds(); // 获取某些其他数据,等待时间10秒
    currentUserId++; //令每个用户id均唯一
    return { id: currentUserId };
}

结语

async/await函数的出现,极大的提高了javascript代码的可读性,但是他们并不是魔法,依然有很多未知的问题等待我们去发现。

我希望你喜欢这篇文章,并认为它游泳。如果有其他的陷阱,或者有任何疑问,请在评论中让我知道

时间: 2024-08-24 14:12:23

ES7 Async/Await 陷阱的相关文章

es7 async await 异步

created 里面 let _this = this; async function asyncAwaitFn1() { return await new Promise((resolve, reject) => { _this.a(resolve); }) } async function asyncAwaitFn2() { return await new Promise((resolve, reject) => { _this.b(resolve); }) } const serial

网易云音乐数据交互—async&await实现版(完结篇)

我们的网易云音乐系列课,尾声了,今天我们要将一个最重要的东西--关于ES7 async结合Fetch异步编程问题. ES7 async/await被称作异步编程的终极解决方案,我们先不管这个称呼,咱们先总结一下,过去5次分享我们一路走来异步编程是如何产生,到最后如何解决的. 第一次分享我们学会了切图和动态计算响应式rem布局,第二次分享我们体会了如何学习使用原生js进行学习轮播图,第三次分享了H5 audio这块,进而引出了第四次的异步请求歌词ajax和第五次的Fetch+promise解决方案

ES7的Async/Await的简单理解

Async/Await 的个人见解 正文: async,顾名思义,一个异步执行的功能,而 await 则是配合 async 使用的另一个关键字,也是闻字识其意,就是叫你等待啦! 二者配合食用效果更佳哦,就像德芙配巧克力 ⊙_⊙|| 现在其实有点意识的前端或者JS学习者基本都学习了ES6语法了,但是依旧感觉在编写异步代码上不够爽怎么办,在 ES7 的 async/await 则能使得我们在编写异步代码时变得像同步一样的方式来编写,这样子可以帮助我们更直观的阅读我们的额代码而不必在一堆代码中去寻找这

JavaScript ES7 中使用 async/await 解决回调函数嵌套问题

原文链接:http://aisk.me/using-async-await-to-avoid-callback-hell/ JavaScript 中最蛋疼的事情莫过于回调函数嵌套问题.以往在浏览器中,因为与服务器通讯是一种比较昂贵的操作,因此比较复杂的业务逻辑往往都放在服务器端,前端 JavaScript 只需要少数几次 AJAX 请求就可拿到全部数据. 但是到了 webapp 风行的时代,前端业务逻辑越来越复杂,往往几个 AJAX 请求之间互有依赖,有些请求依赖前面请求的数据,有些请求需要并行

wepack打包时出错不压缩代码及使用es7(async await)新语法问题

1.打包时出错且不压缩代码是因为没有正确的转换语法 npm install babel-core babel-preset-env babel-loader --save-dev 2.如果使用了async await等es7新语法还要安装 npm install babel-plugin-transform-runtime --save-dev 3.webpack.config.js中配置 module:{ rules:[ { test:/(\.jsx|.js)$/, use:{ loader:

小程序里使用es7的async await语法

我们做小程序开发时,有时候想让自己代码变得整洁,异步操作时避免回调地狱.我们会使用es6的promise. es7的async,await .promise在小程序和云开发的云函数里都可以使用. async和await只能在云开发的云函数里使用.我们在小程序的代码里直接使用,就会报如下错误. 这个报错就是告诉我们不能在小程序里直接使用es7的async和await语法.但是这么好的语法我们用起来确实显得代码整洁,逼格高.那接下来我就教大家如何在小程序代码里使用es7的async和await语法.

理解ES7中的async/await

优势是:就是解决多层异步回调的嵌套 从字面上理解 async/await, async是 "异步"的含义,await可以认为是 async wait的简写,因此可以理解 async 用于声明一个function是异步的,而await用于等待一个异步方法执行完成返回的值(返回值可以是一个Promise对象或普通返回的值).注意:await 只能出现在 async函数中. 1-1 async的作用?首先来理解async函数是怎么处理返回值的,我们以前写代码都是通过return语句返回我们想

体验异步的终极解决方案-ES7的Async/Await

阅读本文前,期待您对promise和ES6(ECMA2015)有所了解,会更容易理解.本文以体验为主,不会深入说明,结尾有详细的文章引用. 第一个例子 Async/Await应该是目前最简单的异步方案了,首先来看个例子. 这里我们要实现一个暂停功能,输入N毫秒,则停顿N毫秒后才继续往下执行. 1 var sleep = function (time) { 2 return new Promise(function (resolve, reject) { 3 setTimeout(function

异步操作要了解的ES7的async/await

1.什么是async.await? async顾名思义是“异步”的意思,async用于声明一个函数是异步的.而await从字面意思上是“等待”的意思,就是用于等待异步完成.并且await只能在async函数中使用. 通常async.await都是跟随Promise一起使用的.为什么这么说呢?因为async返回的都是一个Promise对象同时async适用于任何类型的函数上.这样await得到的就是一个Promise对象(如果不是Promise对象的话那async返回的是什么 就是什么): awa