首先看一個基本寫法:promise
async function demoFunc () { return new Promise((resolve, reject) => { resolve('hello world') }) }
async 寫在函數前,返回一個Promise對象async
async function asyncFunc () { return 'hello world' }
經過控制檯 能夠看到,返回了一個Promise函數
await操做只能用在async函數中,不然會報錯。spa
arg = await awaitFunc
awaitFunc能夠是任何值,一般是一個promise3d
寫一個函數,返回promise對象,該函數會在2s後輸出參數信息code
function printName(name) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(name) }, 2000) } ) }
而後再寫一個async函數,此時就能夠用上咱們的await關鍵字,由於await後一般放的是一個promise對象,因此能夠寫上以上的調用對象
async function getName() { let name = await printName('jack') console.log('hello ', name) } getName() // 2s後 輸出hello jack
代碼的執行過程是調用了getName方法,遇到了await,await表示代碼在這裏暫停了,再也不向下執行,等待promise對象執行完畢,拿到promise resolve的值並返回後,再繼續向下執行。blog
咱們能夠用try catchget
function printName(name) { return new Promise((resolve, reject) => { setTimeout(() => { throw new Error('出錯了') // 模擬報錯 resolve(name) }, 2000) } ) } async function getName () { try { let name = await printName('jack') console.log('hello ', name) } catch (err) { console.log(err, ' 被catch抓到啦') } } getName() // 控制檯輸出 出錯了 被catch抓到啦
也可使用promise的.then() .catch()表達式,等價爲同步
function printName(name) { return new Promise((resolve, reject) => { setTimeout(() => { throw new Error('出錯了') // 模擬報錯 resolve(name) }, 2000) } ) } async function getName () { let name = await printName('jack') return name } // 由於在最前面咱們就知道,async返回的是一個promise對象,此處的getName其實也就是一個promise對象 getName().then((name)=> { console.log('hello ', name) }).catch((err) => { console.log(err, ' 被catch抓到啦') }) // 會進入catch
目前看不出咱們的async和await有什麼妙用。讓咱們來多寫幾個,妙用初體驗
async function getName() { let name1 = await printName('Jack') let name2 = await printName('Bob') let name3 = await printName('Cindy') console.log('hello ', name1, ' ', name2, ' ', name3) } getName() // 6s後輸出 hello Jack Bob Cindy
有沒有感受本身在寫正常的同步代碼了?爽嗎?還能夠更爽,咱們繼續看例子
如今要求使用promise寫一個函數,要求第一步消耗1秒,第二步消耗2秒,第三步消耗3秒,總時間是1+2+3一共6秒,咱們看看promise的鏈式寫法
function getTime(n) { return new Promise(resolve => { setTimeout(() => resolve(n + 1000), n) }) } function step1(n) { console.log(`步驟1消耗${n}秒`) return getTime(n) } function step2(n) { console.log(`步驟2消耗${n}秒`) return getTime(n) } function step3(n) { console.log(`步驟3消耗${n}秒}`) return getTime(n) } // promise鏈式寫法 function doThis() { const time1 = 1000 step1(time1) .then(time2 => step2(time2)) .then(time3 => step3(time3)) .then(retult => { console.log('retult is 'retult) }) } // async函數寫法 async function doThis() { const time1 = 1000 const time2 = await step1(time1) const time3 = await step2(time2) const result = await step3(time3) console.log(`result is ${result}`) } doThis()
看看運行結果,輸出的時間間隔能夠感覺到是1秒,2秒,3秒
有沒有感受不用跟繁瑣的鏈式打交道了。其實需求一變的話,會更明顯。若是咱們需求第一步 第二步 第三步分佈別爲1秒2秒3秒不變。追加需求,第二步須要加上第一步的時間,第三步要加第二步的時間,即第一步1秒,第二步1+2=3秒,第三步3+3=6秒,一共9秒,咱們先看看鏈式寫法
function step1(n) { console.log(`步驟1消耗${n}秒`) return getTime(n); } function step2(m, n) { console.log(`步驟2消耗${m} and ${n}秒`); return getTime(n); } function step3(k, m, n) { console.log(`步驟3消耗${k}, ${m} and ${n}秒`) return getTime(k + m + n); } // Promise方式調用 function doThis() { const time1 = 1000 step1(time1) .then(time2 => { return step2(time1, time2) .then(time3 => [time1, time2, time3]); }) .then(times => { const [time1, time2, time3] = times; return step3(time1, time2, time3); }) .then(result => { console.log(`result is ${result}`) }); } // async/await方式調用 async function doThis() { const time1 = 1000 const time2 = await step1(time1) const time3 = await step2(time1, time2) const result = await step3(time1, time2, time3) console.log(`result is ${result}`) }
能夠明顯感受到輸出間隔1秒 3秒 6秒
最後輸出7是由於咱們的6在step3內getTime(6000)加1000ms變成7000
這個時候感受到async/await的便捷之處了嗎?除了寫法方便,不知道你們發現了沒,咱們的參數能夠直接調用...改天補充,有急事