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

1、什么是async、await?

async顾名思义是“异步”的意思,async用于声明一个函数是异步的。而await从字面意思上是“等待”的意思,就是用于等待异步完成。并且await只能在async函数中使用。

通常async、await都是跟随Promise一起使用的。为什么这么说呢?因为async返回的都是一个Promise对象同时async适用于任何类型的函数上。这样await得到的就是一个Promise对象(如果不是Promise对象的话那async返回的是什么 就是什么);

await得到Promise对象之后就等待Promise接下来的resolve或者reject。

我们先看个例子:

 1 var sleep = function (time) {
 2     return new Promise(function (resolve, reject) {
 3         setTimeout(function () {
 4             resolve();
 5         }, time);
 6     })
 7 };
 8
 9 var start = async function () {
10     // 在这里使用起来就像同步代码那样直观
11     console.log(‘start‘);
12     await sleep(3000);
13     console.log(‘end‘);
14 };
15
16 start();

上面代码控制台运行的结果是:先打印出‘start’,然后等待3秒后打印出“end”,这就是一个简单的async/await的例子。

2、我们需要知道的是:

 1 1、async 表示这是一个async函数,await只能用在这个函数里面。
 2
 3 2、async/await 是一种编写异步代码的新方法。之前异步代码的方案是回调和 promise。
 4
 5 3、async/await 是建立在 promise 的基础上。
 6    await 后面跟着的应该是一个promise对象(当然,其他返回值也没关系,只是会立即执行,不过那样就没有意义了…),
 7    await 表示在这里等待promise返回结果了,再继续执行。
 8
 9 4、async/await 像 promise 一样,也是非阻塞的。
10
11 5、async/await 让异步代码看起来、表现起来更像同步代码。这个是async/await 的真正威力,也可以说是其相比较promise的最大优点。

3、首先了解async函数起什么作用

1 async function test() {
2   return "hello world";
3 }
4
5 const result = test();
6 console.log(result);

浏览器打印出来的是:Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "hello world"}

想一下,如果async函数没有返回值呢?会是什么样?如下代码:

1 async function test() {
2  console.log("111111111")
3 }
4
5 const result = test();
6 console.log(result);

浏览器打印结果如下:
‘111111111’
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: undefined}
也就是说结果返回的是Promise.resolve(undefined)

看到这里明白了吗?async 函数返回的是一个 Promise 对象。也就是说如果我们在async函数中 return 一个常量,async 会把这个常量通过 Promise.resolve() 封装成 Promise 对象。

既然是 Promise 对象,那我们也就可以通过then()方法获取其值,如下

test().then(res => {
    console.log(res);    // 输出 hello world
});

看了上面的代码,是不是很不明白async/await到底有啥用?

我们知道Promise 的特点——无等待,所以在没有 await 的情况下执行 async 函数,它会立即执行,返回一个 Promise 对象,并且,绝不会阻塞后面的语句。这和普通返回 Promise 对象的函数并无二致。

那么下一个关键点就在于 await 关键字了。

4、await 有啥用,做了什么?

await 操作符一般说来是用于等待一个Promise 对象。它只能在异步函数 async function 中使用。但事实是,await后可以是一个 Promise 对象或者任何要等待的值。请参见:await 语法

如果一个 Promise 被传递给一个 await 操作符,await 将等待 Promise 正常处理完成并返回其处理结果

function test(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

async function f1() {
  var x = await test(10);
  console.log(x); // 10
}
f1();

如果该值不是一个 Promise,await 会把该值转换为已正常处理的Promise,然后等待其处理结果。

async function f2() {
  var y = await 20;
  console.log(y); // 20
}
f2();

如果 Promise 处理异常,则异常值被抛出。

async function f3() {
  try {
    var z = await Promise.reject(30);
  } catch (e) {
    console.log(e); // 30
  }
}
f3();

5、async/await 的优势在于处理 then 链

这个是使用async/await最优势的地方

单一的 Promise 链并不能发现 async/await 的优势,但是,如果需要处理由多个 Promise 组成的 then 链的时候,优势就能体现出来了(其实,Promise 通过 then 链来解决多层回调的问题,现在又用 async/await 来进一步优化它,也可以说是async/await基于Promise 做了更好的处理)

假设一个业务,分多个步骤完成,每个步骤都是异步的,而且依赖于上一个步骤的结果。我们仍然用 setTimeout 来模拟异步操作:

下边这几段代码是复制网上的案例,能够说明问题就行。
/**
 * 传入参数 n,表示这个函数执行的时间(毫秒)
 * 执行的结果是 n + 200,这个值将用于下一步骤
 */
function takeLongTime(n) {
    return new Promise(resolve => {
        setTimeout(() => resolve(n + 200), n);
    });
}

function step1(n) {
    console.log(`step1 with ${n}`);
    return takeLongTime(n);
}

function step2(n) {
    console.log(`step2 with ${n}`);
    return takeLongTime(n);
}

function step3(n) {
    console.log(`step3 with ${n}`);
    return takeLongTime(n);
}

现在用 Promise 方式来实现这三个步骤的处理

function doIt() {
    console.time("doIt");
    const time1 = 300;
    step1(time1)
        .then(time2 => step2(time2))
        .then(time3 => step3(time3))
        .then(result => {
            console.log(`result is ${result}`);
            console.timeEnd("doIt");
        });
}

doIt();

// c:\var\test>node --harmony_async_await .
// step1 with 300
// step2 with 500
// step3 with 700
// result is 900
// doIt: 1507.251ms

输出结果 result 是 step3() 的参数 700 + 200 = 900。doIt() 顺序执行了三个步骤,一共用了 300 + 500 + 700 = 1500 毫秒,和 console.time()/console.timeEnd() 计算的结果一致。

如果用 async/await 来实现呢,会是这样

async function doIt() {
    console.time("doIt");
    const time1 = 300;
    const time2 = await step1(time1);
    const time3 = await step2(time2);
    const result = await step3(time3);
    console.log(`result is ${result}`);
    console.timeEnd("doIt");
}

doIt();

结果和之前的 Promise 实现是一样的,但是这个代码看起来是不是清晰得多,几乎跟同步代码一样。

关于async/await 处理 then 链,网上有很多文章,可以搜搜,基本可以理解的差不多。

总结参考文章:https://www.jianshu.com/p/5cae46133bad

function takeLongTime(n) {

return new Promise(resolve => {

setTimeout(() => resolve(n + 200), n);

});

}

原文地址:https://www.cnblogs.com/mahmud/p/11518475.html

时间: 2024-10-25 09:44:56

异步操作要了解的ES7的async/await的相关文章

ES7的Async/Await的简单理解

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

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

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

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

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

JavaScript 的 async/await

随着 Node 7 的发布,越来越多的人开始研究据说是异步编程终级解决方案的 async/await. 异步编程的最高境界,就是根本不用关心它是不是异步. async 函数就是隧道尽头的亮光,很多人认为它是异步操作的终极解决方案. async 和 await 起了什么作用 async 起什么作用 这个问题的关键在于,async 函数是怎么处理它的返回值的! 我们当然希望它能直接通过 return 语句返回我们想要的值,但是如果真是这样,似乎就没 await 什么事了.所以,写段代码来试试,看它到

理解 JavaScript 的 async/await

随着 Node 7 的发布,越来越多的人开始研究据说是异步编程终级解决方案的 async/await.我第一次看到这组关键字并不是在 JavaScript 语言里,而是在 c# 5.0 的语法中.C# 的 async/await 需要在 .NET Framework 4.5 以上的版本中使用,因此我还很悲伤了一阵--为了要兼容 XP 系统,我们开发的软件不能使用高于 4.0 版本的 .NET Framework. 我之前在<闲谈异步调用"扁平"化> 中就谈到了这个问题.无论

async/await 的基本实现和 .NET Core 2.1 中相关性能提升

前言 这篇文章的开头,笔者想多说两句,不过也是为了以后再也不多嘴这样的话. 在日常工作中,笔者接触得最多的开发工作仍然是在 .NET Core 平台上,当然因为团队领导的开放性和团队风格的多样性(这和 CTO 以及主管的个人能力也是分不开的),业界前沿的技术概念也都能在上手的项目中出现.所以虽然现在团队仍然处于疾速的发展中,也存在一些奇奇怪怪的事情,工作内容也算有紧有松,但是总体来说也算有苦有乐,不是十分排斥. 其实这样的环境有些类似于笔者心中的"圣地" Thoughtworks 的

理解ES7中的async/await

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

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函数,前面的例子可以改写这