Async
Node.js 是一個非同步機制的服務端語言,在大量非同步的場景下需要按順序執行,那正常做法就是回撥巢狀回撥,回撥巢狀太多的問題被稱之回撥地獄。
Node.js 為解決這一問題推出了非同步控制流 ———— Async
Async/Await
Async/Await 就 ES7 的方案,結合 ES6 的 Promise 物件,使用前請確定 Node.js 的版本是 7.6 以上。
Async/await的主要益處是可以避免回撥地獄(callback hell),且以最接近同步程式碼的方式編寫非同步程式碼。
基本規則
- async 表示這是一個async函式,await只能用在這個函式裡面。
- await 表示在這裡等待promise返回結果了,再繼續執行。
- await 後面跟著的應該是一個promise物件
對比使用
場景:3秒後返回一個值
原始時代
let sleep = (time, cb) => {
setTimeout(() => {
cb(`ok`);
}, 3000);
}
let start = () => {
sleep(3000, (result) => {
console.log(result)
})
}
start()
Promise 時代
let sleep = (time) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`ok`) ;
}, time);
})
}
let start = () => {
sleep(3000).then((result) => {
console.log(result)
})
}
start()
Async/Await 時代
let sleep = (time) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`ok`) ;
}, time);
})
}
let start = async () => {
let result = await sleep(3000);
console.log(result)
}
start();
捕捉錯誤
let sleep = (time) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(`error`) ;
}, time);
})
}
let start = async () => {
try{
let result = await sleep(3000);
console.log(result)
} catch(err) {
console.log(`error`)
}
}
start();
在迴圈中使用
let sleep = (time) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`ok`) ;
}, time);
})
}
let start = async () => {
for (var i = 1; i <= 3; i++) {
console.log(`當前是第${i}次等待..`);
await sleep(1000);
}
}
start();
爬蟲中使用
const request = require(`request`);
const fs = require(`fs`);
const cheerio = require(`cheerio`);
let spider = (url) => {
return new Promise((resolve, reject) => {
request(url, (error, response, body) => {
resolve(body);
})
})
}
let start = async () => {
let dom = await spider(`http://www.lanrentuku.com/`);
let $ = cheerio.load(dom);
$(`img`, `.in-ne`).each((i, e) => {
let src = $(e).attr(`src`);
let name = src.substr(src.lastIndexOf(`/`) + 1);
request(src).pipe(fs.createWriteStream(name))
})
}
start();