异步流程控制库GoWithTheFlow
2015-11-27 20:36
681 查看
异步流程控制库GoWithTheFlow
一个尾触发方式来控制异步流程的库, 有seq(顺序执行) par(同步执行) 两种方法使用
顺序执行Flow().seq(function(next) { setTimeout(function(){ console.log("first job"); next('error', 'retValue'); },500); }).seq(function(next, error, result) { console.log(error, result); console.log("second job. run *after* first job"); next(); });
同步执行
最后挂载的seq将会在所有par任务执行结束后执行
errors results是数组 保存所有的par的结果
执行结果顺序是挂载任务的顺序
Flow().par(function(next){ setTimeout(function(){ console.log("job foo"); next(null, "foo"); },1000); }).par(function(next){ setTimeout(function(){ console.log("job bar"); next(null, "bar"); },500); }).par(function(next){ setTimeout(function(){ console.log("job zoo"); next(null, "zoo"); },500); }).seq(function(next, errors, results){ console.log("job run *after* the completion of foo and bar"); console.assert(errors.length == 3 && errors[0] === null && errors[1] == null) console.assert(results.length == 3 && results[0] === 'foo' && results[1] == 'bar') next(); })
实现
var Flow = function() { var self, stack = [], //等待所有同步操作完成后开始执行异步的部分 timerId = setTimeout(function() { timerId = null; self._next(); }, 0); return self = { destroy: function() { timerId && clearTimeout(timerId); }, //seq 和par 都只是挂载了函数(把函数保存在了stacks中) 并没有执行 //同步执行的任务都在一个元素中 //比如 stack = [ [f1()], [f2(), f3()], [f4()] ] //表示 f1() f2()f3() f4() 三个顺序执行的任务 其中任务2 f2f3两个函数是并行执行 par: function(callback, isSeq) { if (isSeq || !(stack[stack.length - 1] instanceof Array)) { stack.push([]); } stack[stack.length - 1].push(callback); return self; //链式调用 }, seq: function(callback) { return self.par(callback, true); }, //调用一次_next 解决一次顺序任务 _next: function(err, result) { var errors = [], results = [], callbacks = stack.shift() || [], //callbacks [function(next){....}] nbReturn = callbacks.length, isSeq = nbReturn == 1; //表明是顺序任务 比如上面 [f1()] 这种情况 for (var i = 0; i < callbacks.length; i++) { (function(fct, index) { //fct就是异步函数 fct接受三个参数 fct(next, err, result) //而这个function(err, result) 就是next //next接受两个参数 next('error', 'retValue'); fct(function(error, result) { errors[index] = error; results[index] = result; if (--nbReturn == 0) { //表明此次顺序任务执行完毕 比如上面[f2,f3] 到f3的时候 self._next(isSeq ? errors[0] : errors, isSeq ? results[0] : results) } }, err, result); })(callbacks[i], i); } } } }; // export in common js if (typeof module !== "undefined" && ('exports' in module)) { module.exports = Flow; } // Asynchronous Module Definition - http://requirejs.org/docs/whyamd.html if (typeof define === 'function' && define.amd) { define('Flow', [], function() { return Flow; }); }
相关文章推荐
- 使用google protobuf RPC实现echo service
- Ubuntu下django项目的搭建
- golang expected declaration, found 'IDENT'
- golang IDE 工具liteide打开报错解决方法
- golang IDE 工具liteide打开报错解决方法
- django 1.8中文显示、时区设置
- Guava学习笔记:Google Guava 类库简介
- go 格言
- HDU 5546 Ancient Go
- goke 交叉编译gdb
- (EM算法)The EM Algorithm
- PS设计漂亮的个人透明背景LOGO添加到直播间
- django log(续 续)
- Google 扩张的法门
- <15> go string_formatting
- go的学习资料
- Google Earth API 替换方案
- Got the Best Employee of the year 2015 Star Award
- Go学习日记
- go lang singleton模式