专栏首页前端开发博客await 只在 async 函数中工作

await 只在 async 函数中工作

关于 promise 的一种更优雅的写法 async/await 中,await 只会出现在 async 函数中,我们使用 async/await 时,几乎不需要 .then,因为 await 为我们处理等待;但是在代码的顶层,当我们在 async 函数的外部时,我们在语法上是不能使用 await 的,所以通常添加 .then/catch 去处理最终结果或者 error。

有一种特殊的语法可用一种更舒适的方式使用 promise,称为 “async/await”。它的易于理解和使用简单让人惊讶。

Async 函数

我们从 async 关键字开始。它可以放在函数前,就像这样:

async function f() {
  return 1;
}

函数前的 “async” 意味着一件简单的事情:函数总是会返回 promise。如果代码中有 return<non-promise>,那么 JavaScript 就会自动将其封装到一个带有该值的 resolved promise 中。

例如,上述代码中返回一个带有结果 1 的 resolved promise,我们可以进行测试:

f().then(alert); // 1

…我们可以显式的返回一个 promise,结果相同:

async function f() {
    return Promise.resolve(1);
}

f().then(alert); // 1

因此, async 确保函数返回一个 promise,并在其中封装非 promise。很简单对吧?但不仅仅如此。因为还有 await 关键字,它只在 async 函数中工作,而且非常酷。

Await

// 只在 async 函数中工作 
    let value = await promise;

await 关键字使 JavaScript 等待,直到 promise 得到解决并返回其结果。

下面是一个 promise 在 1s 之后 resolve 的例子:

async function f() {

  let promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("done!"), 1000)
  });

  let result = await promise; // 等待,直到 promise 执行 resolves (*)

  alert(result); // “done!”
}

f();

函数在 (*) 行执行“暂停”,并在 promise 被处理时继续执行, result 变成其结果。上述代码在一秒内显示了 “done!”

我们强调: await 字面上是让 JavaScript 等待 promise 完成,然后继续处理结果。这并不会消耗 CPU 资源,因为引擎可以同时处理其他任务:执行其他脚本,处理事件等。

这是一种比 promise.then 更优雅地获取 promise 结果的语法,它更容易阅读和编写。

不能在常规函数中使用 await 如果我们尝试在非 async 函数中使用 await,就会产生语法错误: function f() { let promise = Promise.resolve(1); let result = await promise; // 语法错误 }

我们用 Promises 链 章节 showAvatar() 示例开始,并使用 async/await 重写它:

  1. 我们需要用 await 替换 .then 调用。
  2. 此外,我们应该使用 async 函数来工作。
async function showAvatar() {

  // 读取我们的 JSON
  let response = await fetch('/article/promise-chaining/user.json');
  let user = await response.json();

  // 读取 GitHub 用户信息
  let githubResponse = await fetch(\`https://api.github.com/users/${user.name}\`);
  let githubUser = await githubResponse.json();

  // 显示化身
  let img = document.createElement('img');
  img.src = githubUser.avatar_url;
  img.className = "promise-avatar-example";
  document.body.append(img);

  // 等待 3 秒
  await new Promise((resolve, reject) => setTimeout(resolve, 3000));

  img.remove();

  return githubUser;
}

showAvatar();

非常整洁,而且易于阅读,对吧?比之前好多了。

await 在顶层代码中无效 刚开始使用 await 的新手往往会忘记这一点,但我们不能在最顶层的代码中编写 await,因为它会无效: // 在顶层代码中导致语法错误 let response = await fetch('/article/promise-chaining/user.json'); let user = await response.json(); 所以我们需要将 await 代码封装在一个async 函数中。就像上述例子一样。 async/awaitpromise.then/catch 我们使用 async/await 时,几乎不需要 .then,因为 await 为我们处理等待。我们也可以使用 try..catch 替代 .catch。但这通常(并不总是)更方便。 但是在代码的顶层,当我们在 async 函数的外部时,我们在语法上是不能使用 await 的,所以通常添加 .then/catch 去处理最终结果或者 error。 与上述示例的 (*) 行一样。

总结

函数前的 async 关键字有两个作用:

  1. 总是返回 promise。
  2. 允许在其中使用 await

在 promise 之前的 await 关键字,使 JavaScript 等待 promise 被处理,然后:

  1. 如果有 error,就会产生异常,就像在那个地方调用了 throwerror 一样。
  2. 否则,就会返回值,我们可以给它分配一个值。

它们一起为编写易于读写的异步代码提供了一个很好的框架。

对于 async/await,我们很少需要编写 promise.then/catch,但我们不应该忘记它们是基于 promise 的。因为有时(例如,在最外面的范围)我们不得不使用这些方法。 Promise.all 也是一个很好的东西,它能够同时等待很多任务。

参考:https://zh.javascript.info/async-await

本文分享自微信公众号 - 前端开发博客(caibaojian_com),作者:前端开发博客

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-11-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 学习CSS Flexbox,玩Flexbox 青蛙游戏

    在学习CSS中,Flexbox是一个比较实用的CSS 布局属性,但很复杂,有些人可能没法很快掌握,今天我要推荐一个跟这个相关的游戏,在游戏中学习Flexbox,...

    前端开发博客
  • 一些有趣的CSS3特性和案例总结

    本文立足vue开源的理念,主要为vue开发者讲解编写vue插件的方法和步骤,通过理论与实践相结合的方式来加深大家对vue插件编写的认识。

    前端开发博客
  • js数组方法的一道笔试题考察点详解

    将数组 var a=[1,2,3] 变成数组 [4,3,2,1] 下面的方式正确的是?

    前端开发博客
  • [译]带你理解 Async/await

    「async/await」是 promises 的另一种更便捷更流行的写法,同时它也更易于理解和使用。

    savokiss
  • 【资讯】大数据与云计算将改变传统数据库技术

    长期以来,企业技术管理者面临着IT架构“自己搭建”还是“外部购买”的两难选择,而随着云数据库和数据库即服务(DBaaS)技术的不断成熟,管理者又...

    小莹莹
  • 数据驱动:传统企业互联网化 互联网业务传统化

    最近接受媒体“SP睿商在线”的采访,谈了一下我对2014年行业发展的一点看法,总结一下,就是“数据驱动:传统企业业务互联网化,互联网企业业务传统化”,转引一下媒...

    数据和云
  • 关于SQL里面两个case when then的应用案例

    (例子二)使用case when then生成虚拟列统计,我们现在的科目数据里面每个人没有分文科和理科类别,如果我们想要按照文科和理科统计,应该怎么写?如下:

    我是攻城师
  • 大数据的新起航如何形成产业化的升级

    如今属于大数据新生的时代,从模式上已经大有所改变,以前的数据只是从各个渠道和分析得到各个数据进行归档,而如今万物互联,借助互联网思维,大数据可以实现一次“凤凰涅...

    企鹅号小编
  • 什么是Promise async await我们用它来做什么?

    async/await是写异步代码的新方式,以前的方法有回调函数和Promise。 async/await是基于Promise实现的,它不能用于普通的回调函数...

    瑞新
  • 如何从Helm v2迁移到Helm v3

    Helm V3 版本已经发布了第三个 Beta 版本了,由于 V2 和 V3 版本之间的架构变化较大,所以如果我们现在正在使用 V2 版本的话,要迁移到 V3 ...

    CNCF

扫码关注云+社区

领取腾讯云代金券