Javascript中的async awai的用法,asyncawai

來源:互聯網
上載者:User

Javascript中的async awai的用法,asyncawai

async / await是ES7的重要特性之一,也是目前社區裡公認的優秀非同步解決方案。目前,async / await這個特性已經是stage 3的建議,可以看看TC39的進度,本篇文章將分享async / await是如何工作的,閱讀本文前,希望你具備Promise、generator、yield等ES6的相關知識。

在詳細介紹async / await之前,先回顧下目前在ES6中比較好的非同步處理辦法。下面的例子中資料請求用Node.js中的request模組,資料介面採用Github v3 api文檔提供的repo代碼倉庫詳情API作為例子示範。

Promise對非同步處理

雖然Node.js的非同步IO帶來了對高並發的良好支援,同時也讓“回調”成為災難,很容易造成回調地獄。傳統的方式比如使用具名函數,雖然可以減少嵌套的層數,讓代碼看起來比較清晰。但是會造成比較差的編碼和調試體驗,你需要經常使用用ctrl + f去尋找某個具名函數的定義,這使得IDE視窗經常上下來回跳動。使用Promise之後,可以很好的減少嵌套的層數。另外Promise的實現採用了狀態機器,在函數裡面可以很好的通過resolve和reject進行流程式控制制,你可以按照順序鏈式的去執行一系列代碼邏輯了。下面是使用Promise的一個例子:

const request = require('request');// 請求的url和headerconst 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);  }); });};getRepoData() .then((result) => console.log(result);) .catch((reason) => console.error(reason););// 此處如果是多個Promise順序執行的話,如下:// 每個then裡面去執行下一個promise// getRepoData()//  .then((value2) => {return promise2})//  .then((value3) => {return promise3})//  .then((x) => console.log(x))

不過Promise仍然存在缺陷,它只是減少了嵌套,並不能完全消除嵌套。舉個例子,對於多個promise串列執行的情況,第一個promise的邏輯執行完之後,我們需要在它的then函數裡面去執行第二個promise,這個時候會產生一層嵌套。另外,採用Promise的代碼看起來依然是非同步,如果寫的代碼如果能夠變成同步該多好啊!

Generator對非同步處理

談到generator,你應該不會對它感到陌生。在Node.js中對於回調的處理,我們經常用的TJ / Co就是使用generator結合promise來實現的,co是coroutine的簡稱,借鑒於python、lua等語言中的協程。它可以將非同步代碼邏輯寫成同步的方式,這使得代碼的閱讀和組織變得更加清晰,也便於調試。

const co = require('co');const request = require('request');const options = { url: 'https://api.github.com/repos/cpselvis/zhihu-crawler', headers: {  'User-Agent': 'request' }};// yield後面是一個產生器 generatorconst getRepoData = function* () { return new Promise((resolve, reject) => {  request(options, (err, res, body) => {   if (err) {    reject(err);   }   resolve(body);  }); });};co(function* () { const result = yield getRepoData; // ... 如果有多個非同步流程,可以放在這裡,比如 // const r1 = yield getR1; // const r2 = yield getR2; // const r3 = yield getR3; // 每個yield相當於暫停,執行yield之後會等待它後面的generator傳回值之後再執行後面其它的yield邏輯。 return result;}).then(function (value) { console.log(value);}, function (err) { console.error(err.stack);});

async / await對非同步處理

雖然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 --save$ npm install babel-preset-es2015 --save$ npm 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));

注意點:

  1. async用來申明裡麵包裹的內容可以進行同步的方式執行,await則是進行執行順序控制,每次執行一個await,程式都會暫停等待await傳回值,然後再執行之後的await。
  2. await後面調用的函數需要返回一個promise,另外這個函數是一個普通的函數即可,而不是generator。
  3. await只能用在async函數之中,用在普通函數中會報錯。
  4. await命令後面的 Promise 對象,運行結果可能是 rejected,所以最好把 await 命令放在 try...catch 代碼塊中。

其實,async / await的用法和co差不多,await和yield都是表示暫停,外麵包裹一層async 或者 co來表示裡面的代碼可以採用同步的方式進行處理。不過async / await裡面的await後面跟著的函數不需要額外處理,co是需要將它寫成一個generator的。

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援幫客之家。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.