1. 程式人生 > >async、await

async、await

git hub .com new repo 執行 順序 返回值 目前

async / await是ES7的重要特性之一,也是目前社區裏公認的優秀異步解決方案。目前,async / await這個特性已經是stage 3的建議。

(1)Promise、generator、yield是ES6中的異步解決方案,使用Promise之後,可以很好的減少嵌套的層數。

function fn(p) {
  return new Promise((resolve, reject) => {
    console.log(p);
    setTimeout(() => {
      console.log(‘test:‘,p);
      resolve();
    }, 
2000); }); } function handlePromise() { fn("aaa") .then(() => { return fn("bbb"); }) .then(() => { return fn("ccc"); }) .catch(reason => console.log(`catch reason: ${reason}`)); } 執行:handlePromise()

Promise仍然存在缺陷,它只是減少了嵌套,並不能完全消除嵌套。對於多個promise串行執行的情況,第一個promise的邏輯執行完之後,我們需要在它的then函數裏面去執行第二個promise,這個時候會產生一層嵌套。另外,采用Promise的代碼看起來依然是異步的!

(2)在Node.js中對於回調的處理,我們經常用的TJ / Co就是使用generator結合promise來實現的,co是coroutine的簡稱。

const co = require(‘co‘);
const request = require(‘request‘);

const options = {
  url: ‘https://api.github.com/repos/cpselvis/zhihu-crawler‘,
  headers: {
    ‘User-Agent‘: ‘request‘
  }
};
// yield後面是一個生成器 generator
const 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); });

(3)雖然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
function fn(p) {
  return new Promise((resolve, reject) => {
    console.log(p);
    setTimeout(() => {
      console.log(‘test:‘,p);
      resolve();
    }, 2000);
  });
}
// 註意點:
// 1.async用來申明裏面包裹的內容可以進行同步的方式執行,await則是進行執行順序控制,
// 每次執行一個await,程序都會暫停等待await返回值,然後再執行之後的await。
// 2.await後面調用的函數需要返回一個promise,另外這個函數是一個普通的函數即可,而不是generator。
// 3.await只能用在async函數之中,用在普通函數中會報錯。
// 4.await命令後面的 Promise 對象,運行結果可能是 rejected,所以最好把 await 命令放在 try...catch 代碼塊中。
// 5.其實,async / await的用法和co差不多,await和yield都是表示暫停,
// 外面包裹一層async 或者 co來表示裏面的代碼可以采用同步的方式進行處理。
// 不過async / await裏面的await後面跟著的函數不需要額外處理,co是需要將它寫成一個generator的。
async function asyncFun() {
 try {
    const result_a = await fn(‘aaa‘);
    const result_b = await fn(‘bbb‘);
    const result_c = await fn(‘ccc‘);
    const result_d = await fn(‘ddd‘);
    // 每個await相當於暫停,執行await之後會等待它後面的函數(不是generator)返回值之後再執行後面其它的await邏輯。
    return result_d;
  } catch (err) {
    console.log(err);
  }
}
執行:asyncFun().then(result => console.log(`result: ${result}`)).catch(err => console.error(err));

參考:

http://www.cnblogs.com/cpselvis/p/6344122.html

http://caibaojian.com/es6/generator.html

async、await