一步一步实现基于Task的Promise库(三)waitFor方法的设计
在上一篇中我们已经完成了Task.js里面的all和any方法,已经可以完美的解决大部分需求,我们再来看一个需求:
我们要先读取aa.txt的内容,然后去后台解析,同时由用户指定一个文件,也要读取解析,然后当两个文件都解析完了,我们还要合并两部分内容存到cc.txt中,最后发个通知说ok了。。
这里的用户是指真正浏览网页的用户,可能是说让用户上传一个文件去读取解析,但是aa.txt是程序定好了的,我们也不希望用户上传文件之后再去读取解析aa.txt,怎么办?如果有一个waitFor方法可以等待另一个任务的完成就好了,请看下面代码:
var taskExp_1 = new Task(readFile, "aa.txt").then(resolveFile, "/service/fileResolve.ashx?file=aa.txt");
var taskExp_2 = new Task(uploadFile, "bb.txt").then(readFile, "bb.txt").then(resolveFile, "/service/fileResolve.ashx?file=bb.txt");
var taskExp_3 = new Task(taskExp_1).waitFor(taskExp_2).then(writeFile, ["cc.txt"]).then(sendMail).start();
$("#btnUpload").click(function (){
taskExp_2.start();
});
上面代码中的waitFor方法并不会导致taskExp_2的执行,如果用户不点击btnUpload按钮来触发taskExp_2.start(); 那么taskExp_3将一直等待taskExp_2的执行并完成,然后才能进行后面的writeFile。嗯,这样确实可以解决这个头疼的需求,下面我们来看看waitFor方法该如何设计呢?
先看看下面两句代码有什么区别?
var taskExp3_2 = new Task(readFile, "bb.txt").waitFor(taskExp3_1).then(mergeContent).start();
var taskExp3_2 = new Task([readFile, "bb.txt"], taskExp3_1).all(mergeContent).start();
区别在于使用all方法会导致taskExp3_1的执行,而waitFor不会,如果没有taskExp3_1.start()这句话,taskExp3_2永远也不可能执行完成,它会一直等待taskExp3_1的执行并完成,除此之外就没有区别了.那么waitFor方法的定位就是设计给那些不希望即时执行的Task的(如果你希望Task的即时执行,那么请用all)
从逻辑上来说上面的taskExp3_1是不需要接收readFile的返回参数的,那么readFile的返回参数实际上是给后面的mergeContent使用的.我们实际上是把
new Task(readFile, "bb.txt").waitFor(taskExp3_1).then(mergeContent).start();
转换成
new Task([readFile, "bb.txt"], taskExp3_1).all(mergeContent).start();
只不过我们不让taskExp3_1触发执行. 然后我们还希望mergeContent回调方法里面可以通过this.Param[0]和this.Param[1]分别取到readFile和taskExp3_1的输出参数.
那么waitFor方法最复杂的情况是什么呢?
var taskExp3_2 = new Task([func1],[func2],[func3]).waitFor(task1, task2).then(callback).start();
只有在func1,func2,func3,task1,task2都执行完成了才会执行callback,并且task1,task2必须自己调用start()触发执行,否则taskExp3_2会一直等待.
其实我们已经发现有点不对劲了,那就是waitFor方法为什么一定要耦合func1,func2,func3的all逻辑呢?
var taskExp3_2 = new Task([func1],[func2],[func3]).all().waitFor(task1, task2).then(lastFunc).start();
这样做是不是更好呢? 答案是肯定的,我们应该设计all(),any(),new Task(),好处是支持了下面几种写法:
//写法一
var taskExp3_2 = new Task([func1],[func2],[func3]).any().waitFor(task1, task2).then(lastFunc).start();
//写法二
var taskExp3_2 = new Task().waitFor(task1, task2).then(lastFunc).start();
//写法三
var task1 = new Task(func1).then([func2],[func3]).all(); //如果没有这个all(),task1的完成就有歧义,是func2,func3都完成才叫完成还是一个完成就叫完成?
var task2 = new Task(task1).then(lastFunc).start();
看来在实现waitFor方法之前我们要先实现all(),any(),new Task()这些不传参的方法,同时这些方法的实现要注意什么呢?
var taskExp3_2 = new Task([func1],[func2]).all().then(callback1);
这句代码应该等效于:
var taskExp3_2 = new Task([func1],[func2]).all(callback1);
同时func1,func2返回的参数不能因为all()的执行而传递不到callback1。在下一章我们来实现这些不传参的方法。
一步一步实现基于Task的Promise库(三)waitFor方法的设计的更多相关文章
- 一步一步实现基于Task的Promise库(五)waitFor和waitForAny的实现
在实现waitFor方法之前,我们先要搞明白下面这些问题: 1. waitFor方法的形参有限制吗? 没有!如果形参是Task类型,不应该启动Task,如果是function类型,会执行方法.所以wa ...
- 一步一步实现基于Task的Promise库(四)无参数的WorkItem
接着上一篇我直接给出代码,现在支持了new Task(), then(), all(), any() 这些不传参的调用方式. (function(){ var isFunction = functio ...
- 一步一步实现基于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的基础.最开始接触 ...
随机推荐
- Timer Swing
一个Swing的例子,按钮控件上中文出现乱码: 试了网上的设置Font,或将汉字使用new String(str.getBytes(),"GBK")对展示的汉字进行编码.都无效. ...
- Oracle性能优化学习笔记WHERE在连接顺序的条款
ORACLE自下而上分析顺序WHERE条款,根据这一原理,表之间的连接必须写在其它WHERE先决条件, 这些条件可以过滤掉要被写入记录的最大数目WHERE在条款结束. 比如: (低效, ...
- 正则表达式 \b (转)
引用网上一段话: \b 是正则表达式规定的一个特殊代码(好吧,某些人叫它元字符,metacharacter),代表着单词的开头或结尾,也就是单词的分界处.虽然通常英文的单词是由空格,标点符号或者换行来 ...
- Tick and Tick------HDOJ杭州电(无法解释,直接看代码)
Problem Description The three hands of the clock are rotating every second and meeting each other ma ...
- Linux互斥和同步应用程序(一):posix线程和线程之间的相互排斥
[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流.请勿用于商业用途] 有了进程的概念,为何还要使用线程呢? 首先,回 ...
- HDU 4932 Miaomiao's Geometry(推理)
HDU 4932 Miaomiao's Geometry pid=4932" target="_blank" style="">题目链接 题意: ...
- GG同步sqlserver报错一个案例 Invalid date format
在里面Oracle表同步sqlserver时间,在sqlserver当应用程序数据的结束.您可能会遇到这个错误. 2014-05-17 17:20:24 WARNING OGG-01154 SQL e ...
- (二)spring MVC配置
使用Maven添加依赖的jar包 <!-- 自动扫描的包名 --> <mvc:reso ...
- ExecutorService 建立一个多线程的线程池的步骤
ExecutorService 建立一个多线程的线程池的步骤: 线程池的作用: 线程池功能是限制在系统中运行的线程数. 依据系统的环境情况,能够自己主动或手动设置线程数量.达到执行的最佳效果:少了浪费 ...
- iOS、真机调试
Xcode中IOS.真机测试 一.购买开发者账号(需要有信用卡.每年支付$99.0) 二.直接淘宝购买一个.用于测试,但是不能上传App 1.获取手机的UUID(Identifier xxxxxx9e ...