Async/Await是ES2017中加入的新特性,解救衆生於Promisejavascript
這篇文章主要根據Async/Await的一個介紹視頻,截圖供你們入門學習java
callback最受詬病的就是嵌套的括號,不美觀,錯誤處理也複雜node
Promise就好不少,結構清晰,統一錯誤處理編程
主角Async/Await登場了,傳統的函數調用方式,線性編程方式dom
注意:下面的示例須要在node>=7.6的環境下,支持async/wait異步
記錄兩個方法運行的時間,總共運行的時間async
processes.js函數
const util = require('util') const wait = util.promisify(setTimeout) module.exports = { async process01 () { console.log('Process 01 started') console.time('Process 01 ended') await wait(5000) console.timeEnd('Process 01 ended') console.log() return 'process01-value' }, async process02 () { console.log('Process 02 started') console.time('Process 02 ended') await wait(3000) console.timeEnd('Process 02 ended') console.log() return 'process02-value' } }
第一行的util是nodejs自帶的工具類,本機須要安裝node工具
第二行util.promisify() 用於將那些接受回調函數的函數,轉變爲 Promiseoop
main.js
const {process01, process02} = require('./processes') async function main () { try { console.time('Total Running Time') const value01 = await process01() const value02 = await process02() console.log('Process 01 Returned: ', value01) console.log('Process 02 Returned: ', value02) console.log() console.timeEnd('Total Running Time') } catch (error) { console.error('error', error) } } main()
結果
異常處理,若是被調用函數沒有處理異常,則會中斷執行調用函數
processes.js
const util = require('util') const wait = util.promisify(setTimeout) module.exports = { async process01 () { console.log('Process 01 started') throw new Error('Process 01 Failed') console.time('Process 01 ended') await wait(5000) console.timeEnd('Process 01 ended') console.log() return 'process01-value' }, async process02 () { console.log('Process 02 started') console.time('Process 02 ended') await wait(3000) console.timeEnd('Process 02 ended') console.log() return 'process02-value' } }
main.js
const {process01, process02} = require('./processes') async function main () { try { console.time('Total Running Time') const value01 = await process01() const value02 = await process02() console.log('Process 01 Returned: ', value01) console.log('Process 02 Returned: ', value02) console.log() console.timeEnd('Total Running Time') } catch (error) { console.error('error', error) } } main()
結果
針對1-2-issue的錯誤處理,在process01中增長了異常處理,不會中斷調用函數的執行
processes.js
const util = require('util') const wait = util.promisify(setTimeout) module.exports = { async process01 () { try { console.log('Process 01 started') throw new Error('Process 01 Failed') console.time('Process 01 ended') await wait(5000) console.timeEnd('Process 01 ended') console.log() return 'process01-value' } catch (error) { console.error(error) } }, async process02 () { try { console.log('Process 02 started') console.time('Process 02 ended') await wait(3000) console.timeEnd('Process 02 ended') console.log() return 'process02-value' } catch (error) { console.error(error) } } }
main.js
const {process01, process02} = require('./processes') async function main () { try { console.time('Total Running Time') const value01 = await process01() const value02 = await process02() console.log('Process 01 Returned: ', value01) console.log('Process 02 Returned: ', value02) console.log() console.timeEnd('Total Running Time') } catch (error) { console.error('error', error) } } main()
結果
並行執行異步函數
processes.js
const util = require('util') const wait = util.promisify(setTimeout) module.exports = { async process01 () { console.log('Process 01 started') console.time('Process 01 ended') await wait(5000) console.timeEnd('Process 01 ended') console.log() return 'process01-value' }, async process02 () { console.log('Process 02 started') console.time('Process 02 ended') await wait(3000) console.timeEnd('Process 02 ended') console.log() return 'process02-value' } }
main.js
const {process01, process02} = require('./processes') async function main () { try { console.time('Total Running Time') const data = await Promise.all([process01(), process02()]) // 並行執行 console.log() console.log('Process 01 Returned: ', data[0]) console.log('Process 02 Returned: ', data[1]) console.log() console.timeEnd('Total Running Time') } catch (error) { console.error('error', error) } } main()
結果
並行執行2個函數,其中一個異步函數拋異常,不影響另外一個函數的執行,但影響返回以後的操做
processes.js
const util = require('util') const wait = util.promisify(setTimeout) module.exports = { async process01 () { console.log('Process 01 started') throw new Error('Process 01 Failed') console.time('Process 01 ended') await wait(5000) console.timeEnd('Process 01 ended') console.log() return 'process01-value' }, async process02 () { console.log('Process 02 started') console.time('Process 02 ended') await wait(3000) console.timeEnd('Process 02 ended') console.log() return 'process02-value' } }
main.js
const {process01, process02} = require('./processes') async function main () { try { console.time('Total Running Time') const data = await Promise.all([process01(), process02()]) // 並行執行 console.log() console.log('Process 01 Returned: ', data[0]) console.log('Process 02 Returned: ', data[1]) console.log() console.timeEnd('Total Running Time') } catch (error) { console.error('error', error) } } main()
結果
被調用的異步函數添加異常處理,一樣能夠返回執行結果,不影響調用函數的繼續執行
processes.js
const util = require('util') const wait = util.promisify(setTimeout) module.exports = { async process01 () { try { console.log('Process 01 started') throw new Error('Process 01 Failed') console.time('Process 01 ended') await wait(5000) console.timeEnd('Process 01 ended') console.log() return 'process01-value' } catch (error) { console.error(error) } }, async process02 () { try { console.log('Process 02 started') console.time('Process 02 ended') await wait(3000) console.timeEnd('Process 02 ended') console.log() return 'process02-value' } catch (error) { console.error(error) } } }
main.js
const {process01, process02} = require('./processes') async function main () { try { console.time('Total Running Time') const data = await Promise.all([process01(), process02()]) // 並行執行 console.log() console.log('Process 01 Returned: ', data[0]) console.log('Process 02 Returned: ', data[1]) console.log() console.timeEnd('Total Running Time') } catch (error) { console.error('error', error) } } main()
結果
某個方法的benchmark, 循環執行10次,計算總耗時和平均耗時
processes.js
const util = require('util') const wait = util.promisify(setTimeout) function getRandBetween (a, b) { return Math.floor(Math.random() * b) + a } module.exports = { async secretAlgorithm () { console.time('secretAlgorithm') await wait(getRandBetween(1, 7) * 100) console.timeEnd('secretAlgorithm') } }
main.js
const now = require('performance-now') const {secretAlgorithm} = require('./processes') const NUMBER_OF_RUNS = 10 async function main () { try { let totalTime = 0 for (let i = 0; i < NUMBER_OF_RUNS; i++) { const start = now() await secretAlgorithm() const end = now() totalTime += (end - start) } console.log() console.log('totalTime: ', totalTime) console.log('Number of retries: ', NUMBER_OF_RUNS) console.log('Average Running Time: ', (totalTime / NUMBER_OF_RUNS).toFixed(3)) } catch (error) { console.error('error', error) } } main()
結果
植5棵樹,打印每棵樹開關的時間, forEach中不能使用await, 能夠使用 for...of 替代
PowerPlant.js
const util = require('util') const wait = util.promisify(setTimeout) function getRandBetween (a, b) { return Math.floor(Math.random() * b) + a } class PowerPlant { constructor (id) { this.id = id } async turnOn () { console.log(`Turning On Power Plant ${this.id}`) console.time(`Power Plant ${this.id} turned on`) await wait(getRandBetween(1, 5) * 200) console.timeEnd(`Power Plant ${this.id} turned on`) console.log() } async turnOff () { console.log(`Turning Off Power Plant ${this.id}`) console.time(`Power Plant ${this.id} turned off`) await wait(getRandBetween(1, 3) * 200) console.timeEnd(`Power Plant ${this.id} turned off`) console.log() } } module.exports = PowerPlant
main.js
const PowerPlant = require('./PowerPlant') let powerPlants = [] async function main () { try { powerPlants.push(new PowerPlant('01')) powerPlants.push(new PowerPlant('02')) powerPlants.push(new PowerPlant('03')) powerPlants.push(new PowerPlant('04')) powerPlants.push(new PowerPlant('05')) /* turn on all of them */ powerPlants.forEach(powerPlant => { await powerPlant.turnOn() }) /* turn off all of them */ powerPlants.forEach(powerPlant => { await powerPlant.turnOff() }) } catch (error) { console.error('error', error) } } main()
結果
processes.js
const util = require('util') const wait = util.promisify(setTimeout) function getRandBetween (a, b) { return Math.floor(Math.random() * b) + a } class PowerPlant { constructor (id) { this.id = id } async turnOn () { console.log(`Turning On Power Plant ${this.id}`) console.time(`Power Plant ${this.id} turned on`) await wait(getRandBetween(1, 5) * 200) console.timeEnd(`Power Plant ${this.id} turned on`) console.log() } async turnOff () { console.log(`Turning Off Power Plant ${this.id}`) console.time(`Power Plant ${this.id} turned off`) await wait(getRandBetween(1, 3) * 200) console.timeEnd(`Power Plant ${this.id} turned off`) console.log() } } module.exports = PowerPlant
main.js
const PowerPlant = require('./PowerPlant') let powerPlants = [] async function main () { try { powerPlants.push(new PowerPlant('01')) powerPlants.push(new PowerPlant('02')) powerPlants.push(new PowerPlant('03')) powerPlants.push(new PowerPlant('04')) powerPlants.push(new PowerPlant('05')) /* turn on all of them */ for(let powerPlant of powerPlants) { await powerPlant.turnOn() } /* turn off all of them */ for(let powerPlant of powerPlants) { await powerPlant.turnOff() } } catch (error) { console.error('error', error) } } main()
結果
某個方法的benchmark, 計算循環執行10次的耗時和平均耗時
const util = require('util') const wait = util.promisify(setTimeout) function getRandBetween (a, b) { return Math.floor(Math.random() * b) + a } module.exports = { async secretAlgorithm () { console.time('secretAlgorithm') await wait(getRandBetween(1, 7) * 100) console.timeEnd('secretAlgorithm') } }
main.js
const now = require('performance-now') const {secretAlgorithm} = require('./processes') const NUMBER_OF_RUNS = 10 async function main () { try { let totalTime = 0 let retries = 0 while (retries < NUMBER_OF_RUNS) { const start = now() await secretAlgorithm() const end = now() totalTime += (end - start) retries++ } console.log() console.log('totalTime: ', totalTime) console.log('Number of retries: ', NUMBER_OF_RUNS) console.log('Average Running Time: ', (totalTime / NUMBER_OF_RUNS).toFixed(3)) } catch (error) { console.error('error', error) } } main()
結果
https://www.youtube.com/watch?v=f57IHEeDNcA