深入理解await与async
<h4 id="1-1await">1-1.await</h4><ul>
<li><code>await</code>的意思就是<strong>等待</strong>。它后面可以跟一个表达式。如果是值(如字符串、数字、普通对象等等)的话,返回值就是本身的值。</li>
<li>不过最常用的是后面跟一个<code>promise</code>对象。<code>await</code>会等待这个<code>promise</code>的状态由<code>pending</code>转为<code>fulfilled</code>或者<code>rejected</code>。在此期间它会阻塞,延迟执行await语句后面的语句。</li>
<li>如果<code>promise</code>对象的结果是<code>resolve</code>,它会将<code>resolve</code>的值,作为<code>await</code>表达式的运算结果。</li>
</ul>
<h5 id="语法糖本质">语法糖本质</h5>
<p> 其实<code>await</code>与<code>async</code>本身就是<code>promise</code>化编程的一种语法糖。对比一下两种写法。</p>
<pre><code class="language-js">// 异步promise化的函数--模拟请求后端接口
function asyncFn () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
if (true) {
console.log('resolve console')
resolve('resolve return')
} else {
reject('reject return')
}
}, 2000)
})
}
// promise
asyncFn().then((res) => {
console.log(res)
}, (err) => {
console.log(err)
})
// await
try {
var res = await asyncFn()
console.log(res)
} catch(err) {
console.log(err)
}
// 如果有第二次请求的话,promise需要在then方法继续调用,再用then接受,过多的嵌套依然会增加阅读难度。而await async只需要像写同步代码一样继续书写就可以,它是解决异步编程回调地狱的终极手段。
</code></pre>
<h5 id="例一">例一</h5>
<pre><code class="language-js">// ps:由于js本身现在已经限制了await必须用在async函数中,否则会报错。所以请将下面的复制粘贴到浏览器控制台查看结果
function asyncFn () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
if (true) {
console.log('resolve console')
resolve('resolve return')
} else {
reject('reject return')
}
}, 2000)
})
}
var value1 = await asyncFn()
var value2 = await 'plain text'
console.log(value1)
console.log(value2)
//浏览器会依次打印 ‘resolve console’ ‘resolve return’ ‘plain text’
</code></pre>
<h5 id="例二">例二</h5>
<p>如果你对结果有疑问,可以将asyncFn前面的await去掉,再在浏览器控制台执行一次。</p>
<p><img src="https://tva1.sinaimg.cn/large/006y8mN6ly1g6kfywwi9aj30t40i40vh.jpg"></p>
<p>这两次对比一下,会发现第二次的<code>resolve console</code>是最后打印出来的,而第一次的是第一个打印的。</p>
<p>根本原因就是第一次代码中<code>await</code>阻塞了后面语句的执行,等待<code>promise</code>确定结果后继续执行后面语句。</p>
<h5 id="例三">例三</h5>
<p>根据前两例可想而知,如果两个<code>await</code>的后面跟着的都是<code>promise</code>对象。那么第二个await等待的时间是它本身等待的时间加上第一个<code>await</code>等待的时间</p>
<pre><code class="language-js">function asyncFn1 () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
if (true) {
console.log('resolve console1')
resolve('resolve return1')
} else {
reject('reject return1')
}
}, 2000)
})
}
function asyncFn2 () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
if (true) {
console.log('resolve console2')
resolve('resolve return2')
} else {
reject('reject return2')
}
}, 2000)
})
}
var value1 = await asyncFn1()
var value2 = await asyncFn2()
// 复制并执行,会发现2s后打印了‘resolve console1’,4s后打印了‘resolve console2’
</code></pre>
<h5 id="思考">思考</h5>
<pre><code class="language-js">// 已经知道了await会阻塞代码的执行,如果我们在实际开发中有这样的代码。
function fn () {
// 假设request是请求后端接口
var value = await request()
console.log(value)
// ...
}
fn()
var arr = []
arr.push('1')
// ...其他不依赖后端接口逻辑
</code></pre>
<p> 在fn调用后,由于<code>await</code>的阻塞,必然会影响到下面的逻辑。在实际开发中,如果后端接口5s才响应,那么下面的代码就需要等待5s。显然这是不合理的,为了解决这种现象,就需要<code>async</code>声明。</p>
<h4 id="1-2async">1-2.async</h4>
<p> 之前我们知道了<code>await</code>会阻塞代码的执行。而解决这个弊端的手段就是<code>async</code>声明。</p>
<pre><code class="language-js">async function asyncFn () {
return 'async'
}
console.log(asyncFn())
</code></pre>
<p> 控制台打印一下,会发现打印的是一个<code>promise</code>对象。而且是<code>Promise.resolve</code>对象。<code>resolve</code>的值就是<code>asyncFn</code>的函数返回值<code>async</code>。</p>
<p><img src="https://tva1.sinaimg.cn/large/006y8mN6ly1g6kh5ejq2mj30lw07ijsn.jpg"></p>
<p> 如果函数没有返回值的话,它自然返回的会是<code>Promise.resolve(undefined)</code>。</p>
<p> <strong>其实之所以<code>async</code>声明能解决<code>await</code>的阻塞问题,就是因为<code>async</code>声明将函数作了一层<code>promise</code>包装,这样内部的异步操作其实就是由<code>pending</code>转为<code>resolve</code>或者<code>reject</code>的过程。这样函数本身就能够随意调用,函数内部的<code>await</code>也不会再影响到函数外部的代码执行。</strong></p><br><br>
来源:https://www.cnblogs.com/jsgoshu/p/11444404.html
頁:
[1]