一步一步实现基于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的基础.最开始接触 ...
随机推荐
- E - Speed Limit(2.1.1)
E - Speed Limit(2.1.1) Time Limit:1000MS Memory Limit:30000KB 64bit IO Format:%I64d & %I ...
- Swift学习——Swift解释特定的基础(七)
Implicitly Unwrapped Optionals 隐式解析选项 如上所述.可选意味着常数或变量"没有值".通过可选if声明来推断是否存在值,假设有值析值. 有时候 ...
- 微软发布Win10开发者指南视频
假设你是一个开发者,推荐你看看微软今天推出了一系列视频,标题是Win10开发人员指南,总体长度6时,多达22章内容,介绍很广泛.其实,即使你是编程新手或仅有兴趣,也值得一看. 开发人员Jerry Ni ...
- js中的open和showModalDialog
一.window.open()支持环境: JavaScript1.0+/JScript1.0+/Nav2+/IE3+/Opera3+ 二.基本语法:window.open(pageURL,name,p ...
- Hybrid----U采用IWebView演出PDF和其他文件
App如果你需要显示pdf.word档,在这个时候有没有其他控制,比UIWebView更适合,这是高度抽象的技术细节,可以非常easy采用 UIWebView打开文件类型列表 watermark/2/ ...
- NYNU_省赛选拔题(10)
题目描述 Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown aetiology, was recog ...
- smb_精简安装
yum install samba vim /etc/samba/smb.conf [修改下自己要发布的目录 .eg : path = /home/iknow] smbpasswd -a ik ...
- 都能看懂的嵌入式linux/android alsa_aplay alsa_amixer命令行使用方法
前几天在嵌入式linux上用到alsa command,网上查的资料多不给力,仅仅有动手一点点查,最终能够用了,将这个用法告诉大家,以免大家少走弯路. 0.先查看系统支持哪几个alsa cmd: ll ...
- ReactJs入门思路
ReactJs入门思路小指南 原文 http://segmentfault.com/blog/fakefish/1190000002449277 React是怎么搞的? React中,把一切东西都看 ...
- 在VirtualBox安装OS X 10.10
下面将指导介绍了如何引入自由和强大VirtualBox安装在虚拟机上OS X Yosemite 10.10 法律免责声明:本指南旨在说明如何在定期购买的苹果电脑上创建一个虚拟机执行真正的Mac OS ...