一步一步实现基于Task的Promise库(四)无参数的WorkItem
接着上一篇我直接给出代码,现在支持了new Task(), then(), all(), any() 这些不传参的调用方式。
(function(){
var isFunction = function (target) {
return target instanceof Function;
};
var isArray = function (target) {
return target instanceof Array;
};
//自定义事件管理(代码摘抄自http://www.cnblogs.com/dolphinX/p/3254017.html)
var EventManager = function(){
this.handlers = {};
};
EventManager.prototype = {
constructor: EventManager,
addHandler: function(type, handler){
if(typeof this.handlers[type] == 'undefined'){
this.handlers[type] = new Array();
}
this.handlers[type].push(handler);
},
removeHandler: function(type, handler){
if(this.handlers[type] instanceof Array){
var handlers = this.handlers[type];
for(var i=0; i<handlers.length; i++){
if(handler[i] == handler){
handlers.splice(i, 1);
break;
}
}
}
},
trigger: function(type, event){
/*
if(!event.target){
event.target = this;
}
*/
if(this.handlers[type] instanceof Array){
var handlers = this.handlers[type];
for(var i=0; i<handlers.length; i++){
handlers[i](event);
}
}
}
};
var WorkItem = function(arrayArgs){
var _subItems = [];
var _checkFunc = function(args){
if(isFunction(args[0])){
if(args.length == 2 && isArray(args[1])){
_subItems.push({'isFunc': true, 'func': args[0], 'args': args[1]});
}
else{
_subItems.push({'isFunc': true, 'func': args[0], 'args': args.slice(1)});
}
return true;
}
return false;
};
var _checkTask = function(task){
if(task instanceof Task){
_subItems.push({'isFunc': false, 'task': task});
}
};
if(!_checkFunc(arrayArgs)){
for(var i=0; i<arrayArgs.length; i++){
if(!_checkFunc(arrayArgs[i])){
_checkTask(arrayArgs[i]);
}
}
}
var _startSubItem = function(subItemIndex, context){
var subItem = _subItems[subItemIndex];
if(subItem.isFunc){
var workItemCxt = context.getWorkItemContext(subItemIndex);
subItem.func.apply(workItemCxt, subItem.args);
}
else{
if(subItem.task.getStatus() == TaskStatus.finished){
context.end(subItem.task.getOutput(), subItemIndex)
}
else{
subItem.task.finished(function(output){
context.end(output, subItemIndex);
});
subItem.task.start(context.inputParams);
}
}
};
this.condition = "";
this.start = function(context){
context.setItemsCount(_subItems.length);
for(var i=0; i<_subItems.length; i++){
_startSubItem(i, context);
}
}
};
//无参数的WorkItem,用于对前一个WorkItem的条件判断,例如all();
//ConditionWorkItem和WorkItem可以看做实现了一个接口{condition:string,start:function}
var ConditionWorkItem = function(){
this.condition = "";
this.start = function(context){
context.triggerEnd();
}
};
var Context = function(endCallback, inputParams){
var _this = this;
var _rawOutputParams = [];
var _itemCount;
//如果无需Test,_isNonTest就等于true(当调用triggerEnd方法时,就应该无需Test,直接下一个WorkItem)
var _isNonTest = false;
var _condition = {
then: function(){
_this.outputParams = _rawOutputParams[0].value;
return true;
},
all: function(){
_this.outputParams = [];
for(var i=0; i<_itemCount; i++){
if(_rawOutputParams[i]){
_this.outputParams[i] = _rawOutputParams[i].value;
}
else{
return false;
}
}
return true;
},
any: function(){
for(var i=0; i<_itemCount; i++){
if(_rawOutputParams[i]){
_this.outputParams = _rawOutputParams[i].value;
return true;
}
}
return false;
}
};
this.inputParams = inputParams;
this.outputParams = null;
this.setItemsCount = function(itemCount){
_itemCount = itemCount;
};
this.testCondition = function(key){
//如果无需Test直接返回true,否则才用Test
return _isNonTest || _condition[key]();
};
this.end = function(output, index){
_rawOutputParams[index] = {
value: output
};
if(endCallback){
endCallback(output);
}
};
this.getWorkItemContext = function(index){
return {
param: _this.inputParams,
end: function(output){
_this.end(output, index);
}
};
};
//手动触发EndCallback,(这个上下文设置成无需Test,this.outputParams就设置成this.inputParams,这样参数就可以传递到下一个WorkItem了)
this.triggerEnd = function(){
_isNonTest = true;
_this.outputParams = _this.inputParams;
if(endCallback){
endCallback(_this.outputParams);
}
};
};
var TaskStatus = {
//未开始
pending: 0,
//正在进行
doing: 1,
//已完成
finished: 2
};
window.Task = function(){
var _status = TaskStatus.pending;
var _wItemQueue = [], _currentItem, _currentContext;
var _eventManager = new EventManager();
var _output;
var _initWorkItem = function(args){
var item;
if(args.length == 0){
item = new ConditionWorkItem();
}
else{
var arrayArgs = [];
for(var i=0; i<args.length; i++){
arrayArgs[i] = args[i];
}
item = new WorkItem(arrayArgs);
}
_wItemQueue.push(item);
return item;
};
var _setItemCondition = function(item, condition){
if(condition){
item.condition = condition;
}
};
var _tryDoNextItem = function(output){
var next = _getCurNextItem();
if(next){
if(_currentContext.testCondition(next.condition)){
_currentItem = next;
_doCurrentItem();
}
}
else{
_status = TaskStatus.finished;
_output = output;
_eventManager.trigger("finish", output);
}
};
var _doCurrentItem = function(contextParam){
if(contextParam) {
_currentContext = new Context(_tryDoNextItem, contextParam);
}
else{
if(_currentContext){
_currentContext = new Context(_tryDoNextItem, _currentContext.outputParams);
}
else{
_currentContext = new Context(_tryDoNextItem);
}
}
_currentItem.start(_currentContext);
};
var _getCurNextItem = function(){
var i=0;
for(; i<_wItemQueue.length; i++){
if(_currentItem == _wItemQueue[i]){
break;
}
}
return _wItemQueue[i + 1];
};
_currentItem = _initWorkItem(arguments);
this.getStatus = function(){
return _status;
};
this.getOutput = function(){
return _output;
};
this.finished = function(callback){
if(callback){
_eventManager.addHandler("finish", callback);
}
};
this.start = function(contextParam){
if(_status == TaskStatus.pending){
_status = TaskStatus.doing;
_doCurrentItem(contextParam);
}
return this;
};
this.then = function(){
var workItem = _initWorkItem(arguments);
_setItemCondition(workItem, 'then');
return this;
};
this.all = function(){
//这个arguments现在可能是空的了!
var workItem = _initWorkItem(arguments);
_setItemCondition(workItem, 'all');
return this;
};
this.any = function(){
var workItem = _initWorkItem(arguments);
_setItemCondition(workItem, 'any');
return this;
};
};
})();
var task = new Task([readFile, "aa.txt"], [readFile, "bb.txt"]).all(writeBack, "cc.txt").start();
现在上面的调用形式同样可以用下面的代码代替:
//测试1
var taskExp_1 = new Task([readFile, "aa.txt"], [readFile, "bb.txt"]).all().then(writeBack, "cc.txt").start();
//测试2
var taskExp_2 = new Task([readFile, "aa.txt"], [readFile, "bb.txt"]).all();
var taskExp_3 = new Task(taskExp_2).then(writeBack, "cc.txt").start();
//测试3
var taskExp_4 = new Task([readFile, "aa.txt"], [readFile, "bb.txt"]).all();
var taskExp_5 = new Task().then(taskExp_4).then(writeBack, "cc.txt").start();
在下一篇,我们再来实现waitFor方法。
一步一步实现基于Task的Promise库(四)无参数的WorkItem的更多相关文章
- 一步一步实现基于Task的Promise库(五)waitFor和waitForAny的实现
在实现waitFor方法之前,我们先要搞明白下面这些问题: 1. waitFor方法的形参有限制吗? 没有!如果形参是Task类型,不应该启动Task,如果是function类型,会执行方法.所以wa ...
- 一步一步实现基于Task的Promise库(三)waitFor方法的设计
在上一篇中我们已经完成了Task.js里面的all和any方法,已经可以完美的解决大部分需求,我们再来看一个需求: 我们要先读取aa.txt的内容,然后去后台解析,同时由用户指定一个文件,也要读取解析 ...
- 一步一步实现基于Task的Promise库(二)all和any方法的设计和实现
在上一篇中我们已经初步完成了Task类,如果仅仅是这些,那么没有多大意义,因为网上这类js库有很多,现在我们来些更复杂的使用场景. 如果我们现在有这样一个需求:我们要先读取aa.txt的内容,然后去后 ...
- 一步一步实现基于Task的Promise库(一)Promise的基本实现
如果我们现在有一个需求,大概是先读取一个文件的内容,再把得到的内容传给后台去解析,最后把解析后的结果再保存到那个文件,按照最原始的做法代码就是下面这个样子的: //读取文件的原始内容 var read ...
- 通过Dapr实现一个简单的基于.net的微服务电商系统(五)——一步一步教你如何撸Dapr之状态管理
状态管理和上一章的订阅发布都算是Dapr相较于其他服务网格框架来讲提供的比较特异性的内容,今天我们来讲讲状态管理. 目录:一.通过Dapr实现一个简单的基于.net的微服务电商系统 二.通过Dapr实 ...
- 通过Dapr实现一个简单的基于.net的微服务电商系统(六)——一步一步教你如何撸Dapr之Actor服务
我个人认为Actor应该是Dapr里比较重头的部分也是Dapr一直在讲的所谓"stateful applications"真正具体的一个实现(个人认为),上一章讲到有状态服务可能很 ...
- 通过Dapr实现一个简单的基于.net的微服务电商系统(七)——一步一步教你如何撸Dapr之服务限流
在一般的互联网应用中限流是一个比较常见的场景,也有很多常见的方式可以实现对应用的限流比如通过令牌桶通过滑动窗口等等方式都可以实现,也可以在整个请求流程中进行限流比如客户端限流就是在客户端通过随机数直接 ...
- 通过Dapr实现一个简单的基于.net的微服务电商系统(九)——一步一步教你如何撸Dapr之OAuth2授权
Oauth2授权,熟悉微信开发的同学对这个东西应该不陌生吧.当我们的应用系统需要集成第三方授权时一般都会做oauth集成,今天就来看看在Dapr的语境下我们如何仅通过配置无需修改应用程序的方式让第三方 ...
- 通过Dapr实现一个简单的基于.net的微服务电商系统(十)——一步一步教你如何撸Dapr之绑定
如果说Actor是dapr有状态服务的内部体现的话,那绑定应该是dapr对serverless这部分的体现了.我们可以通过绑定极大的扩展应用的能力,甚至未来会成为serverless的基础.最开始接触 ...
随机推荐
- c++ primer plus(文章6版本)中国版 编程练习答案第八章
编程练习答案第八章 8.1写输出字符串的函数,存在默认参数表示输出频率,莫感觉1.(原标题太扯了,的问题的细微变化的基础上,含义) //8.1编写一个输出字符串的函数.有一个默认參数表示输出次数,默觉 ...
- HTML基金会2----联系,像, 第,对齐
ios讨论组1团:135718460 在web开发中.排版,布局非常重要,因此我们要把基础的东西打坚固,大家不要 慌,慢慢来. 直接把代码拿过去,直接就能够执行的. 1.标题 2.段落 3.HTML ...
- char与byte差异
很多人刚开始学习(包含I,我已经学会了一年多java该)肯会char和byte怀疑这两个数据类型,相互混淆.今天,大量的信息专门搜索,至byte和char两个数据类型进行了总结和比较.第一批成果与大家 ...
- printf 对齐
printf关于对其的问题(参考有关博客加上自己的一些总结) 1.关于左对齐或右对齐问题, 默认的如果%后没有“-”是右对齐的,如果%后跟“0”,不足的个数用0来填充, 例如:printf(&qu ...
- DataTable转化为List
public List<T> ConvertToList<T>(DataTable dt) where T : new() { // 定义集 ...
- 详解JMeter函数和变量
JMeter函数可以被认为是某种特殊的变量,它们可以被采样器或者其他测试元件所引用.函数调用的语法如下: ${__functionName(var1,var2,var3)} 其中,__function ...
- AJAX及其跨域的主要解决方法
AJAX = Asynchronous JavaScript andXML(异步的 JavaScript 和 XML).通过在后台与服务器进行少量数据交换,使网页实现异步更新.要明白异步交互可以通过同 ...
- DYNAMICRESOLUTION | NODYNAMICRESOLUTION
有时候开启OGG进程的时候较慢,可能是由于须要同步的表太多,OGG在开启进程之前会将须要同步的表建立一个记录而且存入到磁盘中,这样就须要耗费大量的时间.OGG同一时候也提供了DYNAMICRESOLU ...
- 学SpringMVC
http://jinnianshilongnian.iteye.com/blog/1593441
- java阅读器hdfs单纯demo
周围环境:eclipse + eclipse hadoop插入. hadoop + rhel6.4 package test; import java.io.IOException; import j ...