js 異步流程控制之 avQ(avril.queue)

 

廢話前言

 

寫了多年的js,遇到過最蛋疼的事情莫過於callback hell, 相信你們也感同身受。node

業界許多大大也爲此提出了不少不錯的解決方案,我所瞭解的主要有:git

  • 樸靈 event proxy, 簡單明瞭容易上手
  • 老趙的 wind.js, 寫起來最舒坦,最能表達程序順序執行邏輯
  • Promise,我的感受爲解決一個坑引入另一個坑,寫出來的代碼一大坨,代碼可讀性最差

我這人閒着沒事也愛折騰,我也本身造輪子,不爲別的只爲本身代碼寫的舒服流暢.github

傳送門:目前只支持 node.js 環境,之後有時間再增長瀏覽器支持npm

 

簡介

爲啥叫avQ: 全稱是avril.queue由於哥喜歡avril就用她名字命名,跟島國無關api

核心:avQ做爲一個異步流程控制框架包含兩大要素來實現異步流程控制而且編碼方便流暢瀏覽器

  • queue 執行隊列 確保程序邏輯按照順序執行
  • $AwaitData 異步等待數據對象,該對象能夠做爲參數用於下一步異步請求,實現編碼流暢的核心

 

動手avQ

Basic example: q.func, q.$await, q.$each

var q = avQ();
var $fileContent = q.$await(fs.readFile, 'the/path/of/file.txt', function(err, res){    /*此時的this 並非指向q,而是一個新的avQ()對象 因此this實際上就是一個subQueue, this.error()會將error層層上拋默認只上拋不作任何處理,之後章節我會詳細介紹q.func執行的原理*/   this.error(err);     return res; });

 

若是fs.readFile 須要上下文怎麼辦框架

q.$await, q.$each, 以及後面的q.$$await,q.$$each 都支持傳入context做爲第一個參數,例如異步

var $fileContent = q.$await(fs, fs.readFile, 'the/path/of/file.txt', function(err, res){

  this.error(err);

  return res;

});

var $$fileContent = q.$$await(fs, fs.readFile, 'the/path/of/file.txt'); // 會自動將 res 最爲 $awaitData 的結果

var $fileExisted = q.$await(fs.exists, 'the/path/of/file.txt'); // 默認將返回fs.existe 的 callback(existed) 中第一個參existed 數做爲值

 

 

var avQ = require('avril.queue');
var q = avQ();

/* return $AwaitData object */ var $fileContent = q.$await(fs.readFile, 'the/path/of/file.txt' , function(err, fileContent){ this.error(err); return fileContent; }); /* convert the $awaitData' result , return a new $AwaitData object */ var $ids = $fileContent.convert(function($org){ return $org.result().split('\n'); }); /* return $AwaitData object which result is list of */ var $users = q.$each(db.User.findById, $ids, function(err, user){ this.error(err); return user; }); q.func(function(){ console.log( $fileContent.result() ) console.log( $users.realResult() ); }); 

 

Syntax Sugar: q.$$await, q.$$each,

q.$if($awaitData, trueFunc), q.$if($awaitData, trueFunc).$else(), q.$if($awaitData, trueFunc).$elseIf($otherAwaitData, otherTrueFunc)

對於標準的node.js異步調用通常返回值是callback(err, result),ui

var $fileContent = q.$$await(fs.readFile, 'the/path/of/file.txt'); // 跟$await() 的區別在於$await 最後一個參數須要callback: return res;

 

$fileContent在異步請求完畢以後將會自動使用result 做爲結果.this

var avQ = require('avril.queue');
var q = avQ();

var $fileContent, $ids, $users;

/* return $AwaitData object */
var filePath1 = 'the/path/of/file1.txt';
var filePath2 = 'the/path/of/file2.txt';
var $fileExisted = q.$await(fs.exists, filePath1);

q.$if($fileExisted, function(){
  $fileContent = this.$$await(fs.readFile, filePath1);
}).$else(function(){
  $fileContent = this.$$await(fs.readFile, filePath2);

});
q.func(function(){
   
  /* convert the $awaitData' result , return a new $AwaitData object */
  $ids = $fileContent.convert(function($org){
    return $org.result().split('\n');
  }); 

  /*  return $AwaitData object which result is list of */
  $users = this.$$each(db.User.findById, $ids); 

});

q.func(function(){
    console.log( $fileContent.result() ) //只取出第一級 result()
    console.log( $users.realResult() ); // 遞歸取出全部的result()
});

 

 

小結

人無完人,碼無完碼,歡迎你們拍磚,若是你們有興趣我會繼續推出更多api文檔及介紹(你們沒興趣仍是要繼續寫完整,哈哈).

你們要以爲我這個庫有意思不妨給個github start

相關文章
相關標籤/搜索