【CF212E】IT Restaurants (01揹包問題)
阿新 • • 發佈:2020-12-13
async函式
基本概念
async
函式是什麼?一句話,它就是 Generator 函式的語法糖。
將上一章的程式碼改成 async 函式的版本:
const { promisify } = require("util"); const path = require('path') const file1 = path.join(__dirname, './text/1.txt') const file2 = path.join(__dirname, './text/2.txt') const readFileP = promisify(readFile) function* f() { let data1 = yield readFileP(file1) console.log('耶,完成了1,資料是' + data1); let data2 = yield readFileP(file2) console.log('耶,完成了2,資料是' + data2); } //async函式的版本 async function f() { let data1 = await readFileP(file1) console.log('耶,完成了1,資料是' + data1); let data2 = await readFileP(file2) console.log('耶,完成了2,資料是' + data2); }
比較後就會發現,async
函式的版本就是將 Generator 函式的星號(*
)替換成async
,將yield
替換成await
。
定義async函式
使用async關鍵字定義一個async函式:
async function f() {
let data1 = await readFileP(file1)
console.log('耶,完成了1,資料是' + data1);
let data2 = await readFileP(file2)
console.log('耶,完成了2,資料是' + data2);
}
執行async函式
執行async
函式則相當於執行了一個自動執行
async
函式如果返回的結果不是Promise,則會執行結果包裝成一個Promise返回:
async function f() {
console.log(1);
}
f().then(()=>{
console.log(2);
})
async function f() {
console.log(1);
return 'done'
}
f().then(value => {
console.log(value);
})
await關鍵字
與yield
類似,async
函式中可以使用await
關鍵字,await
關鍵字後面一般會寫一個Promise例項,async
await
關鍵字,會將控制權轉回外部環境。
- 如果
await
後面是Promise例項,則會等到該 Promise例項被resolve後,才會把本次await
到下次await
之間的程式碼推到MircoTask(微任務)
中等待執行,並且await
的返回值是該Promise例項resolve的值 - 如果
await
後面不是Promise例項,則會立即將本次await
到下次await
之間的程式碼推到MircoTask(微任務)
中等待執行,並且await
的返回值是等於await
後面表示式的值:
async function f() {
let data = await new Promise((resolve, reject) => {
setTimeout(() => {
resolve('a')
}, 2000)
})
console.log(data);
}
//f()
//console.log('end')
如果await
後面不是Promise 例項
async function f() {
let data = await 'a'
console.log(data);
}
f()
console.log('end');
//end
//a
async函式的錯誤處理
如果Promise被reject或丟擲錯誤,await之後的程式碼不會執行,因此,需要使用try..catch
對await
進行錯誤捕捉:
async function f() {
try {
let data = await new Promise((resolve, reject) => {
setTimeout(() => {
reject('123')
}, 2000)
})
//後續程式碼無法執行
console.log('done');
}catch (e) {
console.log('發生錯誤:',e);
}
}
f()
async函式處理併發非同步任務
如果,async
函式中的每個await
都是等到前面await
resolve後才會執行,如果想併發執行,可以使用Promise.all
:
/*併發處理非同步*/
async function f() {
let time1 = new Date()
let [data1,data2] = await Promise.all([
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('123')
}, 2000)
}),
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('123')
}, 3000)
})
])
console.log(data1,data2,'用時:'+ (new Date() - time1));
}
f()
async函式與Promise的對比
用async
函式寫非同步邏輯相比Promise會更加簡潔,在處理不同非同步結果相互依賴,錯誤處理,if...else分支等情況時更加簡便:
const {readFile} = require('fs')
const { promisify } = require("util");
const path = require('path')
const file1 = path.join(__dirname, './text/1.txt')
const file2 = path.join(__dirname, './text/2.txt')
const file3 = path.join(__dirname, './text/3.txt')
const readFileP = promisify(readFile)
function f1() {
readFileP(file1).then(data1 =>{
console.log('耶,完成了1,資料是' + data1);
return readFileP(file2)
}).then(data2 => {
console.log('耶,完成了1,資料是' + data2);
return readFileP(file3)
}).then(data3 => {
console.log('耶,完成了1,資料是' + data3);
})
}
async function f2() {
let data1 = await readFileP(file1)
console.log('耶,完成了1,資料是' + data1);
let data2 = await readFileP(file2)
console.log('耶,完成了2,資料是' + data1 + data2);
let data3 = await readFileP(file3)
console.log('耶,完成了2,資料是' + data1 + data2 + data3);
}
f()