NODEJS从7.6版本开始开始支持async/await语法支持js异步编程,如果你还没有使用它,以下的示例将会告诉你为何要用async/await取代promise处理异步编程。
关于async/await:
- async/await是处理异步编程的新方法,在这之前js使用的是回调函数和promise来处理异步。
- async/await构建于promise之上,他无法同纯回调函数和nodejs风格的回调函数一同使用。
- async/await和promise一样,是无阻塞的。
- async/await让你的异步编程看起来就想是同步的,这是async/await最大的特点。
如下示例有中的getJSON方法它返回promise,这个promise resolve了个JSON对象,我们调用他并且打印出这个json对象,并且返回"done"
const makeRequest = () => getJSON() .then(data => { console.log(data) return "done" }) makeRequest()
下面是对应的async/await版本
const makeRequest = async () => { console.log(await getJSON()) return "done" } makeRequest()
在此他和promise版本有如下的不同
- 在函数之前我们声明了关键字 async,await关键字只能在声明async关键字的函数内部使用。任何的async函数返回的都是promise,async函数的返回值作为promise resolve的值。
- await getJSON() 意味着只有在getJSON函数的promise resolve值得时候才会执行console方法
async/await有什么有点呢?
- 更简洁
- 更易于进行错误异常的捕获
在使用async/await的时候,你可以通过try/catch捕获同步函数异常的方式来捕获async/await的异常。如下示例 try catch将无法捕获JSON.parse的异常因为他发生在promise的内部。因此我们需要通过.catch方法才能正确的捕获异常。
const makeRequest = () => { try { getJSON() .then(result => { // this parse may fail const data = JSON.parse(result) console.log(data) }) // 注释的方式来捕获异常 // .catch((err) => { // console.log(err) // }) } catch (err) { console.log(err) } }
现在我们通过try catch来捕获async await中的异常
const makeRequest = async () => { try { // this parse may fail const data = JSON.parse(await getJSON()) console.log(data) } catch (err) { console.log(err) } }
3.有时候当我们请求接口的并且发起下一个请求的时候,我们需要取得上一个请求的某个数据才能发起下一个请求。
const makeRequest = () => { return getJSON() .then(data => { if (data.needsAnotherRequest) { return makeAnotherRequest(data) .then(moreData => { console.log(moreData) return moreData }) } else { console.log(data) return data } }) }
如上的嵌套方式,如果层级多的话,代码会变得难以维护,并且易错。下面是async/await的版本,它更具可读性和可维护性
const makeRequest = async () => { const data = await getJSON() if (data.needsAnotherRequest) { const moreData = await makeAnotherRequest(data); console.log(moreData) return moreData } else { console.log(data) return data } }
4。调度值
你可能有这样的需求,你调用promise1,然后使用promise1返回的值去调用promise2,然后使用这两个promise返回的结果调用promise3,如下:
const makeRequest = () => { return promise1() .then(value1 => { return promise2(value1) .then(value2 => { return promise3(value1, value2) }) }) }
如果promise3并不依赖与value1,你可能会想让promise更扁平话些,以此来避免深层次的嵌套:
const makeRequest = () => { return promise1() .then(value1 => { return Promise.all([value1, promise2(value1)]) }) .then(([value1, value2]) => { return promise3(value1, value2) }) }
现在看起来似乎可读性提高了。这里把value1和value2放到一个数组里看起来似乎有点奇怪,除了避免promise的嵌套。相同的逻辑我们可以通过async/await来改造它。让他看起来更加的具备可读性。
const makeRequest = async () => { const value1 = await promise1() const value2 = await promise2(value1) return promise3(value1, value2) }