蜀道难难不难 發表於 2021-9-17 10:13:00

JavaScript中的async/await详解

<h2 id="1前言">1、前言</h2>
<p>​    async函数,也就是我们常说的async/await,是在ES2017(ES8)引入的新特性,主要目的是为了简化使用基于Promise的API时所需的语法。<code>async</code>和<code>await</code>关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用Promise。</p>
<h2 id="2详解">2、详解</h2>
<p>​    async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。需要注意的是<code>await</code>关键字只在async函数内有效,如果在async函数体之外使用它,会抛出语法错误。</p>
<h3 id="21async">2.1、async</h3>
<p>​    async函数返回一个 Promise对象,可以使用then方法添加回调函数。只要使用async,不管函数内部返回的是不是Promise对象,都会被包装成Promise对象。</p>
<p>话不多说,上代码看效果:</p>
<h4 id="211函数返回非promise对象">2.1.1、函数返回非Promise对象</h4>
<pre><code class="language-javascript">async function testAsync() {
    return "hello async";
}

const result = testAsync();
console.log(result);
</code></pre>
<p><img src="https://img2020.cnblogs.com/blog/775046/202109/775046-20210917094130508-247318763.png" alt="" loading="lazy"></p>
<p>​    可以看出函数直接返回字符串时,返回的是Promise对象,相当于直接通过Promise.resolve()将字符串封装为Promise对象。如果函数没有返回值时,PromiseResult结果为undefined。</p>
<h4 id="212函数返回promise对象">2.1.2、函数返回Promise对象</h4>
<pre><code class="language-javascript">        async function testAsync() {
                return new Promise(function(resolve, reject) {
                        if (true) {
                                resolve('resolve return')
                        } else {
                                reject('reject return')
                        }
                })
        }
        console.log(testAsync());
</code></pre>
<p><img src="https://img2020.cnblogs.com/blog/775046/202109/775046-20210917094311432-1295460171.png" alt="" loading="lazy"></p>
<p>可以看出返回的也是Promise对象。</p>
<h3 id="22await">2.2、await</h3>
<p>​    await关键字可以跟在任意变量或者表达式之前,但通常await后面会跟一个异步过程。await使用时,会阻塞后续代码执行。我们先抛开async,单独谈await。</p>
<p>​    由于await只能在async标识的函数内使用,以下例子请在浏览器控制台执行看效果。</p>
<pre><code class="language-javascript">function testAsync() {
        return new Promise(function(resolve, reject) {
                setTimeout(function() {
                        if (true) {
                                console.log('请求中...')
                                resolve('resolve return')
                        } else {
                                reject('reject return')
                        }
                }, 2000)
        })
}
var result = await testAsync();
var result1 = await "testAsync后执行";
console.log(result);
console.log(result1);
</code></pre>
<p><img src="https://img2020.cnblogs.com/blog/775046/202109/775046-20210917094347157-781641248.png" alt="" loading="lazy"></p>
<p>​    可以看出,使用了await后,必须得等testAsync方法执行完后,才会执行后续代码。您也可以尝试一下把testAsync前的await去掉,看看跟加上await时有啥区别。</p>
<h3 id="23asyncawait结合使用">2.3、async、await结合使用</h3>
<p>​    上面我们知道了await会阻塞后续代码运行,那怎么解决这个问题呢?就需要用到async,使用async后,函数执行时,一旦遇到await就会先返回一个Promise对象,等到await后的操作完成后,再接着执行async函数体内的语句。</p>
<p>​    先上语法:</p>
<pre><code class="language-javascript"> async function 函数名() {
        await XXX;
}
</code></pre>
<p>​    上示例代码:</p>
<pre><code class="language-javascript">function testAsync() {
        return new Promise(function(resolve, reject) {
                setTimeout(function() {
                        if (true) {
                                console.log('请求中...')
                                resolve('resolve return')
                        } else {
                                reject('reject return')
                        }
                }, 2000)
        })
}

function testAsync2() {
        return new Promise(function(resolve, reject) {
                setTimeout(function() {
                        if (true) {
                                console.log('请求中2...')
                                resolve('resolve return2')
                        } else {
                                reject('reject return2')
                        }
                }, 2000)
        })
}

async function test() {
        console.log('test开始...');
        var value1 = await testAsync();
        console.log(value1);
        var value2 = await testAsync2();
        console.log(value2);
        var value3 = await 'test结束...';
        console.log(value3);
}

console.log(test());
</code></pre>
<p><img src="https://img2020.cnblogs.com/blog/775046/202109/775046-20210917094411509-815847560.png" alt="" loading="lazy"></p>
<p>​    上图可以看出遇到第一个await后,立即返回了Promise对象,然后再按顺序去执行testAsync函数,等待testAsync函数执行后再去执行testAsync2函数。还可以看出async函数可以简化Promise的语法,以往我们需要使用.then去处理回调,现在我们可以使用await像写同步代码一样去写异步代码。</p>
<p>​    我们再升级一下,在上面的基础上再加入两个普通函数:</p>
<pre><code class="language-javascript">function fun1() {
        return '函数1'

}

function fun2() {
        return '函数2'
}

function fun3() {
        console.log(fun1());
        console.log(test()); // async/await函数
        console.log(fun2());
}

console.log(fun3());
</code></pre>
<p><img src="https://img2020.cnblogs.com/blog/775046/202109/775046-20210917094430382-1752582504.png" alt="" loading="lazy"></p>
<p>我们先梳理一下函数的执行过程,</p>
<p>1、先执行函数1</p>
<p>2、进入test函数并输出开始</p>
<p>3、在test函数中遇到await,立即返回Promise对象</p>
<p>4、执行函数2</p>
<p>5、执行test函数中的testAsync方法</p>
<p>6、等到test函数中的testAsync方法执行完后,继续执行testAsync2方法</p>
<p>7、test函数结束</p>
<p>​    可以看出,async函数在遇到await后会立即返回Promise对象,继续执行async函数外部后续逻辑,async函数内部会被await阻塞并按顺序执行代码逻辑。</p>
<h3 id="24asyncawait异常处理">2.4、async、await异常处理</h3>
<p>​    await后面的函数是有可能出现异常的,所以最好把await命令放在try...catch代码块中。如果await后是Promise对象,也可以使用.catch进行捕获。</p>
<pre><code class="language-javascript"> // 第一种写法
async function myFunction() {
   try {
   await something();
   } catch (err) {
   console.log(err);
   }
}

// 第二种写法
async function myFunction() {
   await somethingPromise()
   .catch(function (err) {
   console.log(err);
   });
}
</code></pre>
<h2 id="3总结">3、总结</h2>
<p>​    async函数在遇到await后会立即返回Promise对象,继续执行async函数外部逻辑,async函数内部会被await阻塞并按顺序执行代码逻辑。</p>
<p>​    可以使用try...catch或.catch对async函数进行异常处理。</p>


</div>
<div id="MySignature" role="contentinfo">
    <div style="border: 1px solid #979696;margin: 30px 0;"></div>
<div class="m-reward">
    <div class="m-desc">本文作者:gaozejie</div>
    <div class="m-desc">本文链接:https://www.cnblogs.com/gaozejie/p/15303316.html</div>
    <div class="m-desc">版权声明:本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。</div>
</div><br><br>
来源:https://www.cnblogs.com/gaozejie/p/15303316.html
頁: [1]
查看完整版本: JavaScript中的async/await详解