你肯定要先了解以下重点内容:

你要把 JS 里执行分为两种。

第一种是实打实必须由 JS 线程执行的,比方做一些去算一个文件的 MD5 值,这种个别没人写异步,没益处,都是同步计算。

第二种不是由 JS 线程去执行,只是 JS 把工作提交给它,而后傻了吧唧的啥也不干等它实现并返回后果给本人。比方你调用浏览器接口去网络上下载图片,此时你的 JS 线程是把工作提交给了浏览器,而后始终等浏览器把后果返回给你。干活的是浏览器不是你 JS 线程。

对于不干活的状况,就得用异步的写法了,不然轻则执行效率低下,重则页面卡死,毕竟页面上那么多事等着 JS 线程去干,特地是当初的网站内容都是靠 JS 动静加载的。

以前应用的办法是回调,就是调用接口时同时传一个函数,通知浏览器或谁执行完工作时调用函数,而后咱们在函数中放一些须要执行完工作能力解决的事件。

比方让浏览器去下图片,咱们就把显示图片放到函数中,这个函数就被称为回调函数。你们常见的什么 onload 、onready 都是这个意思。

function download(callback) {    // 这个下载破费 5 秒钟    let file = "我是文件哦"    setTimeout(() => callback(file), 5000)}console.log("开始执行了~")console.log("先去下个图片~")// 下载好了告诉我就行,不等你了download((file) => {    console.log("下载实现:" + file)    console.log("显示图片")})console.log("做其余事件去了~")// 开始执行了~// 先去下个图片~// 做其余事件去了~// 5 秒后......// 下载实现:我是文件哦// 显示图片

但如果,我要下个文件,他的下载链接保留在 A文件里, A文件的下载链接保留在 B文件里, B文件的下载链接保留在 C文件里。

那我必须先下C文件,等C下完了拿到B的链接下B文件,再等B下完了去下A文件,最初能力在A文件里拿到我的文件下载链接。(没有这么蠢的场景,但多个工作顺次依赖前一个工作实现能力解决的状况还是很常见的)

这样就会造成多层嵌套的回调,就被称为回调天堂。

function download(callback) {    // 这个下载破费 5 秒钟    let file = "我是文件哦"    setTimeout(() => callback(file), 5000)}console.log("开始执行了~")console.log("先去下个文件~")// 下载好了告诉我就行,不等你了download((file) => {    console.log("下载 C 实现")    console.log("拿到 B 的链接")    download((file) => {        console.log("下载 B 实现")        console.log("拿到 A 的链接")        download((file) => {            console.log("下载 A 实现")            console.log("拿到 最终文件 的链接")            download((file) => {                console.log("下载 最终文件 实现")            })        })    })})console.log("做其余事件去了~")

于是乎,async + await 就呈现了,它能够让咱们用看起来像同步的形式去写异步的程序。

对于 async 和 await 千万不要恐怖,你把它们了解成回调的语法糖就行了,而回调函数的内容就是 await 之后的局部。

第一段的代码就能够改写成:

async function download() {    // 这个下载破费 5 秒钟    return new Promise((resolve, reject) => {        let file = "我是文件哦"        setTimeout(() => resolve(file), 5000)    })}async function showImage() {    let file = await download()    // 以下是之前回调函数的内容    console.log("下载实现:" + file)    console.log("显示图片")}console.log("开始执行了~")console.log("先去下个图片~")showImage()console.log("做其余事件去了~")// 开始执行了~// 先去下个图片~// 做其余事件去了~// 5 秒后......// 下载实现:我是文件哦// 显示图片

不过乍看之下如同还稍微简单了一点,但如果改写第二个程序呢?

async function download() {    // 这个下载破费 5 秒钟    return new Promise((resolve, reject) => {        let file = "我是文件哦"        setTimeout(() => resolve(file), 5000)    })}async function getFile() {    let file = await download()    console.log("下载 C 实现")    console.log("拿到 B 的链接")    file = await download()    console.log("下载 B 实现")    console.log("拿到 A 的链接")    file = await download()    console.log("下载 A 实现")    console.log("拿到 最终文件 的链接")    file = await download()    console.log("下载 A 实现")    console.log("下载 最终文件 实现")}console.log("开始执行了~")console.log("先去下个图片~")getFile()console.log("做其余事件去了~")

回调天堂不见了,咱们只用一个函数就实现了所有的内容,代码真是太清新了,async + await 真是太厉害了。