1.需求说明
刚接手一个项目,有个文件上传分类功能,但每次只能操作一个文件,测试需要几十个上百个文件,效率实在太低了。
于是让公司小弟改为可以支持批量上传,小弟在写的时候,发现后端只能一个文件处理结束后,才能接收下一个,在后端不修改的情况下,只能写递归来实现。
html代码
<input type="file" name="file" multiple id="file" onchange="angular.element(this).scope().onSelectFile(this)"/>
js代码如下 固定写死file.files[0],就是把文件传递给后台服务,然后后台处理完毕后再调用回调函数。
onSelectFile:function(){
this.voucherService.createResource(
file.files[0],
function(res){
this.$scope.currentVoucher.state = 0;
this.pushResource(res);
}.bind(this));
},
2.第一版的递归实现
小弟改造为可以支持文件批量,递归代码如下:
// 上传多张图片
onSelectFile: function(){
this.uploadRule(0, file.files.length, null,function(b){
this.$scope.currentVoucher.state = 0;
this.pushResource(b);
}.bind(this));
},
uploadRule: function(count, sum, result, next){
if(count == sum){
next(result);
}else{
this.uploadRun(count, function(a){
count++;
result = a;
this.uploadRule(count, sum, result, next);
}.bind(this));
}
},
uploadRun: function(count, cb){
this.voucherService.createResource(
file.files[count],
function(res){
cb(res);
}.bind(this));
},
百科下,递归关系就是实体自己和自己建立关系
嘛,本来不是那么难的逻辑,怎么感觉小弟写的理解起来好绕,缺点就是
- 回调太多,uploadRule(self)->uploadRun->callback->uploadRule(self),就是self与self相距太遥远了,所以增加了理解难度
- 传递参数太多,且变量名count, sum让人摸不着头脑
3.改造的递归实现
于是改为如下方式
// 上传多张图片
onSelectFile: function(){
this.uploadRule(0,null);
},
uploadRule: function(index, result){
if(index < file.files.length){
//单个文件发送不停递归发送
this.voucherService.createResource(
file.files[index],
function(res){
index++;
result = res;
this.uploadRule(index, result);//回调函数中调用下一个文件
}.bind(this));
}else{//结束递归
this.$scope.currentVoucher.state = 0;
this.pushResource(result);
}
},
改造说明:
- 由于callback是通信层的异步回调,在异步框架中这是不可简化的,但是uploadRun是可以去掉的。这样可以
尽量显式的让实体自己和自己建立关系,回归递归本身意义
。 - 简化参数传递
- 递归游标需要传递,但是本样例中的结束条件参数file.files.length本身就是全局变量,就不用在递归函数间来回传递了;像二叉树逆转、快速排序、归并排序采用自判断
- 结束递归的处理函数,原来是通过句柄方式进行回调,函数句柄要不停传递到条件结束来执行;其实句柄是没有必要作为参数传递的,句柄中的逻辑直接平铺到递归函数的主体代码中更便于理解。
- 参数命名,小弟用了count和sum,正常的理解是count用来数个数,sum用来求和,但在本递归中使用明显不合适,本递归中需要传递的是数组下标,用index更符合些
时间: 2024-10-29 03:23:30