雖然co是社區里面的優秀異步解決方案,但是并不是語言標準,只是一個過渡方案。ES7語言層面提供async / await去解決語言層面的難題。目前async / await 在 IE edge中已經可以直接使用了,但是chrome和Node.js還沒有支持。幸運的是,babel已經支持async的transform了,所以我們使用的時候引入babel就行。在開始之前我們需要引入以下的package,preset-stage-3里就有我們需要的async/await的編譯文件。
無論是在Browser還是Node.js端都需要安裝下面的包。
npm install babel-core --savenpm install babel-preset-es2015 --savenpm install babel-preset-stage-3 --save
這里推薦使用babel官方提供的require hook方法。就是通過require進來后,接下來的文件進行require的時候都會經過Babel的處理。因為我們知道CommonJs是同步的模塊依賴,所以也是可行的方法。這個時候,需要編寫兩個文件,一個是啟動的js文件,另外一個是真正執行程序的js文件。
啟動文件index.js
require('babel-core/register');
require('./async.js');
真正執行程序的async.js
const request = require('request');const options = {url: 'https://api.github.com/repos/cpselvis/zhihu-crawler',headers: {'User-Agent': 'request'}
};const getRepoData = () => {return new Promise((resolve, reject) => {request(options, (err, res, body) => {if (err) {reject(err);}resolve(body);});});
};async function asyncFun() {try {const value = await getRepoData();// ... 和上面的yield類似,如果有多個異步流程,可以放在這里,比如// const r1 = await getR1();// const r2 = await getR2();// const r3 = await getR3();// 每個await相當于暫停,執行await之后會等待它后面的函數(不是generator)返回值之后再執行后面其它的await邏輯。return value;} catch (err) {console.log(err);}
}asyncFun().then(x => console.log(`x: ${x}`)).catch(err => console.error(err));
注意點:
- async用來申明里面包裹的內容可以進行同步的方式執行,await則是進行執行順序控制,每次執行一個await,程序都會暫停等待await返回值,然后再執行之后的await。
- await后面調用的函數需要返回一個promise,另外這個函數是一個普通的函數即可,而不是generator。
- await只能用在async函數之中,用在普通函數中會報錯。
- await命令后面的 Promise 對象,運行結果可能是 rejected,所以最好把 await 命令放在 try...catch 代碼塊中。
其實,async / await的用法和co差不多,await和yield都是表示暫停,外面包裹一層async 或者 co來表示里面的代碼可以采用同步的方式進行處理。不過async / await里面的await后面跟著的函數不需要額外處理,co是需要將它寫成一個generator的。
promise.then().catch()的catch通過async/await怎么處理???
try {const value = await getRepoData();return value;} catch (err) {console.log(err);}
牛逼解釋: https://segmentfault.com/a/1190000007535316