1.同步API與異步API
同步API:只有當前API執行完成後,才能繼續執行下一個API;異步API:當前API的執行不會阻塞後續代碼的執行。
2.兩者之前的區別
①同步API可以從返回值中拿到API執行的結果,但是異步API是不可以的。異步API獲取返回值是通過回調函數(自己定義函數讓別人去調用)
②代碼執行順序不同
3.在異步API中,如果後面的代碼需要依賴異步API返回的結果,應該如何處理呢?
舉個例子:在這個文件中需要依次讀取三個文件,當第一個文件讀取完成之後在讀取第二個文件,第二個讀取完成之後在讀取第三個文件。共有三種方法:
1)嵌套
const fs = require('fs')
fs.readFile('./1.txt', 'utf8', (err, result1) => {
console.log(result1);
fs.readFile('./2.txt', 'utf8', (err, result2) => {
console.log(result2);
fs.readFile('./3.txt', 'utf8', (err, result3) => {
console.log(result3);
})
})
})
這樣可以實現依次讀取文件,但是存在多層回調的問題,會形成回調地獄。
2)Promise
const fs = require('fs')
function p1() {
return new Promise((resolve, reject) => {
fs.readFile('./1.txt', 'utf8', (err, result) => {
resolve(result)
})
})
}
function p2() {
return new Promise((resolve, reject) => {
fs.readFile('./2.txt', 'utf8', (err, result) => {
resolve(result)
})
})
}
function p3() {
return new Promise((resolve, reject) => {
fs.readFile('./3.txt', 'utf8', (err, result) => {
resolve(result)
})
})
}
p1().then((r1) => {
console.log(r1);
return p2()
})
.then((r2) => {
console.log(r2);
return p3()
})
.then((r3) => {
console.log(r3);
})
3)異步函數
promise可以解決回調地獄的問題,但是promise寫法有些複雜。在ES7中,新增的異步函數對promise對象進行了分裝,暴露了一些接口,同時也可以解決回調地獄的問題。
const fs = require('fs')
// 改造現有異步函數API,讓其返回promise對象,從而支持異步函數語法
const promisify = require('util').promisify;
// 調用promisify方法改造現有異步API,讓其返回promise對象
const readFile = promisify(fs.readFile)
async function run () {
let r1 = await readFile('./1.txt', 'utf8')
let r2 = await readFile('./2.txt', 'utf8')
let r3 = await readFile('./3.txt', 'utf8')
console.log(r1);
console.log(r2);
console.log(r3);
}
run()