关于一个递归逻辑的代码优化建议

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-08-23 20:42:15

关于一个递归逻辑的代码优化建议的相关文章

PHP中递归函数的一个常见逻辑问题

首先,我们得知道递归函数是什么东西,通俗来讲也就是自己调用自己本身的函数. 现在需要设计一段代码,解决1到10叠加的问题. 代码A: <?php //递归函数 $num=10; function add($sum){ static $tot; if($sum>=1){ $tot+=$sum; add(--$sum); }else{ return $tot; } } echo add($num); ?> 代码B: <?php //递归函数 $num=10; function add(

怎样写出一个递归程序

作为小白,我看到递归程序只是能看懂,但是自己写不出来,我知道要有一个临界条件(这个并不难找),但我不知道怎么演进,这让我十分头疼,因此找到了一篇个人认为写的不错的文章如下,根据我对递归的理解和疑问对原文做了一些标注,欢迎各位大佬,写下自己对递归的理解,本小白感激不尽. 如何写一个递归程序 总是听到大大们说递归递归的,自己写程序的时候却用不到递归.其中的原因,一个是害怕写递归,另一个就是不知道什么时候用递归.这篇文章就浅析一下,希望看完之后不再害怕递归,这就是本文最大的目的. 递归到底有什么意义?

python编程规范与代码优化建议

1.严格使用缩进来体现代码的逻辑从属关系. python对代码的缩进是硬性要求,这一点必须时刻注意.如果某个代码段的缩进不对,那么整个程序就是错的,要么是语法错误无法执行,要么是逻辑错误导致错误结果,而检查这样的错误会花费很多时间. 2.每个import语句只导入一个模块,最好按标准库.扩展库.自定义库的顺序依次导入. 尽量避免导入整个库,最好只导入确实需要使用的对象,这会让程序运行更快. 3.最好在每个类.函数定义和一段完整的功能代码之后增加一个空行,在运算符两侧各增加一个空格,逗号后面增加一

推荐四十多条纯干货 Java 代码优化建议

代码优化最重要的作用应该是避免未知的错误,因此在写代码的时候,从源头开始注意各种细节,权衡并使用最优的选择,将会很大程度上避免出现未知的错误,从长远看也极大的降低了工作量.所以说代码优化的目标是减小代码体积.提高代码运行效率.优化是无止境的,本文也只给出整理的一些常见优化建议. (1)尽量指定类.方法的 final 修饰符. 带有 final 修饰符的类是不可派生的.在 Java 核心 API 中,有许多应用 final 的例子,例如 java.lang.String,整个类都是 final 的

一个简单的ExtJS搜索建议框

封装的是一个Ext4.2的组件,继承并兼容于Ext的ComboBox. 实现原理非常easy,在 combo 中监听 keyup 事件就可以. 搜索建议的Combo.基本上全然兼容, 使用方式与Combo下拉框一样. 须要后台程序依据keyword进行搜索建议. 源代码例如以下: // 搜索建议框,使用时请适当改动包名 Ext.define("CNC.view.SearchComboBox",{ extend: "Ext.form.field.ComboBox",

分享一个递归无限级拼接Json的方法---ExtJs的TreePanel和TreeGrid均适用(Ef,Lambda,Linq,IQueryable,List)

话不多说,先上实体类,如果你不是codefirst,就把它当成数据表结构. 下面是底层BaseDal获取数据的方法  (如果你没有Base类,直接写在你的DAL层和BLL层) 下面是BaseService的方法 下面方法用于拼接字符串 主体方法-- 1 /// <summary> 2 /// 得到树TreePanel的Json 3 /// </summary> 4 /// <returns></returns> 5 public string GetAllL

用VerilogHDL设计一个与门逻辑,并进行前仿和后仿

执行菜单命令[File]-[New Project Wizard-],创建工程向导. 在What is the working directory for this project?下选择项目存储地址工作目录,What is the name of this project?下填写工程名,最后一栏填写顶层文件名. 添加已存在文件(可选),在[File name]下选择已经存在的工程项目,利用[Add]或[Add all]命令添加文件到新工程,点击[Next] 3.选择器件,[Device fam

PHP 代码优化建议

1.尽量静态化: 如果一个方法能被静态,那就声明它为静态的,速度可提高1/4,甚至我测试的时候,这个提高了近三倍.当然了,这个测试方法需要在十万级以上次执行,效果才明显.其实静态方法和非静态方法的效率主要区别在内存:静态方法在程序开始时生成内存,实例方法在程序运行中生成内存,所以静态方法可以直接调用,实例方法要先成生实例,通过实例调用方法,静态速度很快,但是多了会占内存.任何语言都是对内存和磁盘的操作,至于是否面向对象,只是软件层的问题,底层都是一样的,只是实现方法不同.静态内存是连续的,因为是

一个安邦逻辑漏洞爆破密码的py脚本

漏洞地址: 安邦保险集团存在逻辑漏洞可遍历用户ID暴力破解用户原始密码进而重置用户密码(附脚本) http://www.wooyun.org/bugs/wooyun-2010-0119851 脚本POC如下: key:逻辑点.web请求.嵌套 #!/usr/bin/python#coding: utf-8import sysimport urllibimport urllib2def get_headers(dt):    headers = {            'Accept': '*/