前言
随着 JavaScript 语言的不断发展,ES7 中新增了 async/await 关键字,用以解决异步编程带来的回调地狱问题。async/await 使得异步代码的语法更加清晰简洁,使得代码的可读性和可维护性得到了极大地提升。本文将简单介绍 async/await 的基本使用方法,着重分析 async/await 的原理,以帮助读者深入理解其工作原理。
async/await 基本使用方法
在 JavaScript 中,使用 async/await 进行异步编程,需要满足以下条件:
- 函数声明为 async
- await 只能在 async 函数内部使用
- await 右侧必须是 Promise 对象,或者是能够返回 Promise 对象的函数
下面是一个简单的 async 函数示例:
async function getAsyncData() { const data = await fetch('/api/data'); return data.json(); }
在这个例子中,getAsyncData 是一个异步函数,通过 await 关键字等待 Promise 对象的返回。在这个例子中,使用 await 等待了 fetch 函数的返回结果。fetch 返回的是 Promise 对象,await 等待其异步获取到数据,并且将解析为 json 格式。函数返回 Promise 对象,当异步操作完成后 Promise 对象会被 resolve 成异步操作的结果。
async/await 实现原理
async/await 的实现原理就是生成器函数的自动执行器,也就是说,async/await 是基于生成器函数的实现。只不过 async/await 帮助我们实现了生成器函数的自动执行流程,使得生成器函数更加简单易用。
为了更好的理解 async/await 的实现原理,需要了解以下几个关键点:
生成器函数
生成器函数可以使用 yield 关键字控制函数的执行流程。配合使用 next 方法,可以使得生成器函数分多次执行,每次执行到 yield 关键字处暂停,返回到上一级函数中。下次调用 next 方法时,从暂停的位置继续执行。
下面是一个简单的生成器函数示例:
function* helloWorldGenerator() { yield 'hello'; yield 'world'; return 'ending'; }
这个生成器函数每次调用 next 方法都会返回一个对象:包括 value (即 yield 关键字后面的值)和 done (表示调用 next 方法是否正常结束)。
const hw = helloWorldGenerator(); console.log(hw.next()); // { value: 'hello', done: false } console.log(hw.next()); // { value: 'world', done: false } console.log(hw.next()); // { value: 'ending', done: true }
Promise 对象
Promise 对象能够将异步操作转化为同步操作,并且使用了 then 方法控制异步操作的状态。异步操作的结果最终会被 resolve 或者 reject。
下面是一个异步操作的 Promise 对象示例:
function fetchData(url) { return new Promise((resolve, reject) => { fetch(url) .then(response => response.json()) .then(data => resolve(data)) .catch(error => reject(error)); }); }
async/await 实现原理
async 函数实际上就是生成器函数的语法糖,返回的是 Promise 对象。我们一般通过 await 关键字控制异步操作的执行流程。当 await 等待的 Promise 对象完成后,async 函数将会自动执行下一步操作。
下面是一个 async/await 示例:
async function getAsyncData() { const data = await fetchData('/api/data'); return data; }
在这个示例中,getAsyncData 函数使用 await 关键字等待 fetchData 函数返回 Promise 对象完成,完成后将获得数据并将数据返回。返回的数据使用 Promise 对象的形式返回,异步操作完成后 Promise 对象会被 resolve 成异步操作的结果。
实际上,async 函数等价于以下两部分代码:
-- -------------------- ---- ------- -------- -------------- - ------ ------------------------------------ - ----- -------- ------------------------- - --- - ----- ----- - ----- ------------- ------ - ------ ----- ---- -- - ----- ----- - ------ - ------ ---------- ----- ---- -- - -
其中 asyncHandle 函数就是生成器函数的自动执行器。它负责控制异步操作的执行流程,处理异步操作完成后返回的值。
当 async 函数执行时,会返回一个 Promise 对象。这个 Promise 对象在 async 函数内部实现,由 asyncHandle 函数返回。要注意的是这个 Promise 对象的状态是异步操作的状态,而不是 async 函数执行的状态。在 async 函数内部,我们使用 await 关键字等待 Promise 对象的完成。当 Promise 对象完成时,asyncHandle 函数会将 Promise 对象 resolve 为异步操作完成的结果。
getAsyncData() .then(result => console.log(result)); // { value: [异步操作的数据], done: true }
总结
ES7 中加入的 async/await 关键字是解决异步编程回调地狱的一种很好的方法。async/await 帮助我们更好的控制异步编程的流程,使得代码更加清晰易读。async/await 的原理并不复杂,只要理解了生成器函数和 Promise 对象的原理,就可以轻松掌握其实现原理。学习 async/await,可以帮助我们更好的掌握 JavaScript 的异步编程,提高代码的可读性和可维护性。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/65b8c2a2add4f0e0ff1566a4