異步編程(1) Generator

異步的概念

一般同步的程序是請求文件-等待文件-處理文件,而異步則是在等待文件的階段可以處理其他任務,這便是異步

回調函數

Js通過回調函數實現異步編程,回調函數就是將處理文件這一階段單獨卸載一個函數里,等再次執行這個任務時便直接調用該函數

fs.readFile('/etc/passwd', function(err, data){ 
/*
這里便是回調函數
只有當讀取到/etc/passwd時才會執行
*/
  if(err) throws err
  console.log(data)
})

Promise

不過如果依次讀取多個文件時會出現多重嵌套,這便是callback hell

/*callback hell*/
fs.readFile(fileA, function (err, data) {
  fs.readFile(fileB, function (err, data) {
    // ...
  });
});

Promise就是為了解決這個問題才出現的,它提供一個新的寫法

var readFile = require('fs-readfile-promise');
/*返回一個Promise版本的readFile函數*/

readFile(fileA)
.then(function(data){ /*Promise提供then方法加載回調函數*/
  console.log(data.toString());
})
.then(function(){
  return readFile(fileB);
})
.then(function(data){
  console.log(data.toString());
})
.catch(function(err) {/*catch方法捕捉拋出錯誤*/
  console.log(err);
});

協程(coroutine)

通過管理函數執行權來獲得異步編程能力
通過yield命令,可以讓同步中的請求文件跟處理文件中斷開來并且通過這開辟的新的時間來處理其他任務,這便是協程

function asnycJob() {
  // ...其他代碼
  var f = yield readFile(fileA);/*執行到這里后執行權交給其他協程,暫停該進程*/
  // ...其他代碼
}

Generator函數

協程在ES6中的實現,最大特點是可以交出函數的執行權

function* gen(x) { /*在函數名之前加星號以示區別*/
  var y = yield x+2
  return y
}
var g = gen(1);
g.next() // { value: 3, done: false }
g.next() // { value: undefined, done: true }

調用Generator函數執行該函數是不會返回結果而是返回指針對象
通過調用指針的.next()方法會指向第一個遇到的yield語句,也就是分階段執行Generator函數
每次調用next方法都會返回當前階段信息

  • value: yield語句后面表達式的值,表示當前階段的值
  • done: 表示Generator函數是否執行完畢

簡單來說Generator函數就是一個封裝的異步任務的容器,在異步操作需要暫停的地方都用yield語句注明,再通過.next()方法來分階段輸出

Generator函數的數據交換和錯誤處理

.next()方法返回value屬性便是對外輸出的數據,同樣next方法也可以接受參數,賦值給value

function* gen(x){
  var y = yield x + 2;
  return y;
}

var g = gen(1);
g.next() // { value: 3, done: false }
g.next(2) // { value: 2, done: true }

使用指針對象g的throw方法拋出的錯誤可以被函數體被的try..catch代碼捕獲

g.throw('warming!!!')

Generator用法

var fetch = require('node-fetch');
  function* gen(){ 
    var url = 'https://api.github.com/users/github'; 
    var result = yield fetch(url);  /*當需要的時候在fetch該api*/
    console.log(result.bio);}/*.bio: 數據*/

使用該方法

var g = gen();
var result = g.next();

result.value.then(function(data){
  return data.json();
}).then(function(data){
  g.next(data);
});

參考:
http://www.ruanyifeng.com/blog/2015/04/generator.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 簡介 基本概念 Generator函數是ES6提供的一種異步編程解決方案,語法行為與傳統函數完全不同。本章詳細介紹...
    呼呼哥閱讀 1,093評論 0 4
  • 在此處先列下本篇文章的主要內容 簡介 next方法的參數 for...of循環 Generator.prototy...
    醉生夢死閱讀 1,463評論 3 8
  • 異步編程對JavaScript語言太重要。Javascript語言的執行環境是“單線程”的,如果沒有異步編程,根本...
    呼呼哥閱讀 7,336評論 5 22
  • 上一篇介紹了Promise異步編程,可以很好地回避回調地獄。但Promise的問題是,不管什么樣的異步操作,被Pr...
    張歆琳閱讀 1,461評論 0 13
  • 官方中文版原文鏈接 感謝社區中各位的大力支持,譯者再次奉上一點點福利:阿里云產品券,享受所有官網優惠,并抽取幸運大...
    HetfieldJoe閱讀 6,400評論 9 19