废话前言

写了多年的js,遇到过最蛋疼的事情莫过于callback hell, 相信大家也感同身受。

业界许多大大也为此提出了很多不错的解决方案,我所了解的主要有:

  • 朴灵 event proxy, 简单明了容易上手
  • 老赵的 wind.js, 写起来最舒坦,最能表达程序顺序执行逻辑
  • Promise,个人感觉为解决一个坑引入另外一个坑,写出来的代码一大坨,代码可读性最差

我这人闲着没事也爱折腾,我也自己造轮子,不为别的只为自己代码写的舒服流畅.

传送门:目前只支持 node.js 环境,以后有时间再增加浏览器支持

简介

为啥叫avQ: 全称是avril.queue因为哥喜欢avril就用她名字命名,跟岛国无关

核心: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),

var $fileContent = q.$$await(fs.readFile, 'the/path/of/file.txt'); // 跟$await() 的区别在于$await 最后一个参数需要callback: return res;

$fileContent在异步请求完毕之后将会自动使用result 作为结果.

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

js 异步流程控制之 avQ(avril.queue)的更多相关文章

  1. js异步流程控制-回调

    f1为耗时操作,f2依赖f1的数据,因此f2必须在f1之后执行: 个人理解是:将f2(回调函数)的代码放在异步函数内部的最后执行,相当于把同步操作的代码融合到异步函数内部的最后: let tag = ...

  2. nodejs进阶(7)—async异步流程控制

    Async介绍 Async是一个流程控制工具包,提供了直接而强大的异步功能.基于Javascript为Node.js设计,同时也可以直接在浏览器中使用. Async提供了大约20个函数,包括常用的 m ...

  3. 使用yield进行异步流程控制

    现状 目前我们对异步回调的解决方案有这么几种:回调,deferred/promise和事件触发.回调的方式自不必说,需要硬编码调用,而且有可能会出现复杂的嵌套关系,造成"回调黑洞" ...

  4. 异步流程控制库GoWithTheFlow

    异步流程控制库GoWithTheFlow 一个尾触发方式来控制异步流程的库, 有seq(顺序执行) par(同步执行) 两种方法 博客 http://notes.jetienne.com/2011/0 ...

  5. 【javascript】Promise/A+ 规范简单实现 异步流程控制思想

    ——基于es6:Promise/A+ 规范简单实现 异步流程控制思想  前言: nodejs强大的异步处理能力使得它在服务器端大放异彩,基于它的应用不断的增加,但是异步随之带来的嵌套.难以理解的代码让 ...

  6. node核心:异步流程控制

    Node.js的异步是整个学习Node.js过程中重中之重. 1)异步流程控制学习重点 2)Api写法:Error-first Callback 和 EventEmitter 3)中流砥柱:Promi ...

  7. Nodejs中使用异步流程控制Async

    首先,我们都知道,Node基于事件驱动的异步I/O架构,所谓异步就是非阻塞,说白了就是一个事件执行了,我不必等待它执行完成后我才能执行下一个事件.所以在Node环境中的模块基本都是异步的,上一篇说到我 ...

  8. (一)Nodejs - 框架类库 - Nodejs异步流程控制Async

    简介 Async是一个流程控制工具包,提供了直接而强大的异步功能 应用场景 业务流程逻辑复杂,适应异步编程,减少回调的嵌套 安装 npm insatll async 函数介绍 Collections ...

  9. async 异步流程控制规则

    github 学习async网址 : https://github.com/caolan/async/ 1.Async 函数介绍 async 主要实现了三个部分的流程控制功能 1.集合:Collect ...

随机推荐

  1. Nginx 的 Location 配置指令块

    最近一段时间在学习 Nginx ,以前一直对 Nginx 的 Location 配置很头大,最近终于弄出点眉目.总结如下:nginx 配置文件,自下到上分为三种层次分明的结构: |    http b ...

  2. 不同服务器数据库之间的数据操作 sp_addlinkedserver

    --创建链接服务器  exec sp_addlinkedserver   'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 '  exec sp_addlinkedsrv ...

  3. 在eclipse中首次新建项目的时候,出现Project interpreter not specified

    在eclipse中首次新建项目的时候,出现Project interpreter not specified(大致可以理解为:没有执行的项目编译者) 原因就是安装了pydev之后,我们的python还 ...

  4. JS函数的属性

    1.arguments.callee //经典的阶乘(递归)函数 function factorial(num) { if (num <= 1) { return 1; } else { ret ...

  5. hdu 3926 Hand in Hand

    http://acm.hdu.edu.cn/showproblem.php?pid=3926 这道题是判断两个图是不是同构相似.只要判断图中环的个数和链的个数,和每个环的节点数和链的节点数是否相等. ...

  6. 锁机制与原子操作 <第四篇>

    一.线程同步中的一些概念 1.1临界区(共享区)的概念 在多线程的环境中,可能需要共同使用一些公共资源,这些资源可能是变量,方法逻辑段等等,这些被多个线程共用的区域统称为临界区(共享区),临界区的资源 ...

  7. ListView.setOnItemClickListener无效

    如果ListView中的单个Item的view中存在checkbox,button等view,会导致ListView.setOnItemClickListener无效, 事件会被子View捕获到,Li ...

  8. Kth Largest Element in an Array 解答

    Question Find the kth largest element in an unsorted array. Note that it is the kth largest element ...

  9. SVN trunk、branch、tag的用法

    Subversion有一个很标准的目录结构,是这样的.比如项目是proj,svn地址为svn://proj/,那么标准的svn布局是svn://proj/|+-trunk+-branches+-tag ...

  10. Beauty of Array(模拟)

    M - M Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status P ...