热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Async/await学习:写在前面渣渣新人的首篇外文文章翻译

本文是一篇翻译文章,介绍了async/await的用法和特点。async关键字被放置在函数前面,意味着该函数总是返回一个promise。文章还提到了可以显式返回一个promise的方法。该特性使得async/await更易于理解和使用。本文还提到了一些可能的错误,并希望读者能够指正。

Async/await

写在前面

渣渣新人的首篇外文文章翻译!!存在错误可能会很多,如有错误,烦请各位大大指正出来,感谢!

本篇为翻译!

本篇为翻译!

本篇为翻译!

Async/await

有一种特殊的语法可以更舒适地与promise协同工作,它叫做async/await,它是非常的容易理解和使用。

Async functions

让我们先从async关键字说起,它被放置在一个函数前面。就像下面这样:

async function f() {

return 1

}

函数前面的async一词意味着一个简单的事情:这个函数总是返回一个promise,如果代码中有return 语句,Javascript会自动把返回的这个value值包装成promise的resolved值。

例如,上面的代码返回resolved值为1的promise,我们可以测试一下:

async function f() {

return 1

}

f().then(alert) // 1

我们也可以显式的返回一个promise,这个将会是同样的结果:

async function f() {

return Promise.resolve(1)

}

f().then(alert) // 1

所以,async确保了函数返回一个promise,即使其中包含非promise。够简单了吧?但是不仅仅只是如此,还有另一个关键词await,只能在async函数里使用,同样,它也很cool。

Await

语法如下:

// 只能在async函数内部使用

let value = await promise

关键词await可以让Javascript进行等待,直到一个promise执行并返回它的结果,Javascript才会继续往下执行。

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

async function f() {

let promise = new Promise((resolve, reject) => {

setTimeout(() => resolve('done!'), 1000)

})

let result = await promise // 直到promise返回一个resolve值(*)

alert(result) // 'done!'

}

f()

函数执行到(*)行会‘暂停’,当promise处理完成后重新恢复运行, resolve的值成了最终的result,所以上面的代码会在1s后输出'done!'

我们强调一下:await字面上使得Javascript等待,直到promise处理完成,

然后将结果继续下去。这并不会花费任何的cpu资源,因为引擎能够同时做其他工作:执行其他脚本,处理事件等等。

这只是一个更优雅的得到promise值的语句,它比promise更加容易阅读和书写。

不能在常规函数里使用await

如果我们试图在非async函数里使用await,就会出现一个语法错误:

function f() {

let promise = Promise.resolve(1)

let result = await promise // syntax error

}

如果我们忘记了在函数之前放置async,我们就会得到这样一个错误。如上所述,await只能在async函数中工作。

让我们来看promise链式操作一章中提到的showAvatar()例子,并用async/await重写它。

1.我们需要将.then()替换为await

2.此外,我们应该让函数变成async,这样await才能够工作

async function showAvatar() {

// read our JSON

let response = await fetch('/article/promise-chaining/user.json')

let user = await response.json()

// read github user

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'

documenmt.body.append(img)

// 等待3s

await new Promise((resolve, reject) => {

setTimeout(resolve, 3000)

})

img.remove()

return githubUser

}

showAvatar()

相当的简洁和易读,比以前的要好得多。

await不能工作在顶级作用域

那些刚开始使用await的人们老是忘记这一点,那就是我们不能将await放在代码的顶层,那样是行不通的:

// 顶层代码处syntax error

let response = await fetch('/article/promise-chaining/user.json')

let user = await response.json()

所以我们需要将await代码包裹在一个async函数中,就像上面的例子一样。

await接受thenables(好吧我这个渣渣并不知道thenables该如何翻译,有人能告知吗?)

就像promise.then,await也允许使用thenable对象(那些具有可调用的then方法的对象)。同样,第三方对象可能不是一个promise,但是promise的兼容性表示,如果它支持.then方法,那么它就能用于await。

例如,这里await接受了new Thenable(1)

class Thenable {

constructor(num) {

this.num = num

}

then(resolve, reject) {

alert(resolve) // function() {native code}

// 1000ms后将this.num*2作为resolve值

setTimeout(()=> {resolve(this.num * 2), 1000})

}

}

async function(f) {

// 等待1s,result变为2

let result = await new Thenable(1)

alert(result)

}

f()

如果await得到了一个带有then方法的非promise对象,它将会调用提供原生函数resolve、reject作为参数的方法,然后await一直等待,直到他们其中的一个被调用(在上面的例子它发生在(*)行)。

async方法

一个class方法同样能够使用async,只需要将async放在它之前就可以

就像这样:

class Waiter {

async wait () {

return await Promise.resolve(1)

}

}

new Waiter().wait().then(alert) // 1

这里的意思是一样的:它确保了返回值是一个promise,支持await

错误处理

如果一个promise正常resolve,那么await返回这个结果,但是在reject的情况下会抛出一个错误,就好像在那一行有一个throw语句一样。

async function f() {

await Promise.reject(new Error('whoops!'))

}

和下面一样

async function f() {

throw new Error('Whoops!')

}

在真实的使用场景中,promise在reject抛出错误之前可能需要一段时间,所以await将会等待,然后才抛出一个错误。

我们可以使用try-catch语句捕获错误,就像在正常抛出中处理异常一样:

async function f() {

try {

let response = await fetch('http://no-such-url')

} catch (err) {

alet(err) // TypeError: failed to fetch

}

}

f()

如果发生了一个错误,控制会跳转到catch块。当然我们也能够捕获多行语句:

async function f() {

try {

let response = await fetch('/no-user-here')

let user = await response.json()

} catch(err) {

// 在fetch和response.json中都能捕获错误

alert(err)

}

}

f()

如果我们不使用try-catch,然后async函数f()的调用产生的promise变成reject状态的话,我们可以添加.catch去处理它:

async function f() {

let response = await fetch('http://no-such-url')

}

// f()变成了一个rejected的promise

f().catch(alert) // TypeError: failed to fetch

如果我们忘记添加.catch,我们就会得到一个未被处理的promise错误(能够在控制台里看到它),这时我们可以通过使用一个全局的事件处理器去捕获错误,就像在Promise链式操作一章讲的那样。

async/await和promise.then/catch

当我们使用async/await,我们很少需要.then,因为await总是等待着我们,而且我们能够使用常规的try-catch而不是.catch,这通常(并不总是)更方便。

但是在代码的顶层,当我们在async函数的外部时,我们在语法上是不能使用await的,所以通常添加.then/catch去处理最终结果或者错误。

async/await能够与Promise.all友好的协作

当我们需要等待多个promise时,我们可以将他们包装在Promise.all中然后使用await:

// 直到数组全部返回结果

let results = await Promise.all([

fetch(url1),

fetch(url2),

...

])

如果发生了一个错误,它就像普通情况一样:从一个失败状态的promise到Promise.all,然后变成了一个我们能够使用try-cathc去捕获的异常。

总结

放在一个函数前的async有两个作用:

1.使函数总是返回一个promise

2.允许在这其中使用await

promise前面的await关键字能够使Javascript等待,直到promise处理结束。然后:

1.如果它是一个错误,异常就产生了,就像在那个地方调用了throw error一样。

2.否则,它会返回一个结果,我们可以将它分配给一个值

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

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



推荐阅读
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • 本文详细解析了JavaScript中相称性推断的知识点,包括严厉相称和宽松相称的区别,以及范例转换的规则。针对不同类型的范例值,如差别范例值、统一类的原始范例值和统一类的复合范例值,都给出了具体的比较方法。对于宽松相称的情况,也解释了原始范例值和对象之间的比较规则。通过本文的学习,读者可以更好地理解JavaScript中相称性推断的概念和应用。 ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • 本文总结了Java中日期格式化的常用方法,并给出了示例代码。通过使用SimpleDateFormat类和jstl fmt标签库,可以实现日期的格式化和显示。在页面中添加相应的标签库引用后,可以使用不同的日期格式化样式来显示当前年份和月份。该文提供了详细的代码示例和说明。 ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • 一、路由首先需要配置路由,就是点击good组件进入goodDetail组件配置路由如下{path:goodDetail,component:goodDetail}同时在good组件中写入如下点击事件,路由中加入 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
author-avatar
以下犯上LOVE_845
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有