您当前的位置: 首页 > 学无止境 > JS经典实例 网站首页JS经典实例
使用JavaScript大数据导出excel
发布时间:2020-02-16 10:55:56编辑:雪饮阅读()
事情的起因是这样的,我们的商务给我发来一个后台导出功能报错的问题
这一看就是数据量过大,php所需内存不足,导致无法导出的原因。
后台看了下这里的逻辑是视图中分页了,但是当导出时就直接取的所有的,那么这样1282页的数据量所占的内存就已经超过目前配备内存了,如果仅仅只是提升内存配备上限,那么迟早会遇到下次数据量更大的时候再次遇到内存不足的。
那么我的解决思路是这样的,模仿视图分页,导出时候走ajax请求,先获取当前有多少页,然后通过for循环最大页数进行批量请求每个分页的数据并在每个请求完成后合并结果集,这样无论多大数据只是时间问题,最终都能导出。
那么在实施的时候由于自己经验尚缺,还是遇到了一点点问题。
弯路1:以为使用了promise就能避免异步,直接在for中使用了promise,结果发现,for执行完了promise才执行。。。
弯路2:为了解决promise异步,又了解了下Promise.all,这个虽然可以实现批量请求并且同步按顺序请求,但是前提是,Promise.all中的promise实例列表的每一个实例都需要预先创建好,如你创建了fun1,fun2,然后将这两个function放进去,尝试动态创建多个匿名方法(方法体就是返回的promise实例)形成的数组,给这个Promise.all,结果发现,最后执行的结果就是把这几个匿名方法都给我在then的结果中,而并没有挨个去执行,要我在the的结果中去执行。。。,好吧,那么我又尝试不要匿名方法,直接形成promise实例数组,结果发现形成promise实例数组创建过程中promise就已经开始请求了。。。原来promise实例立马创建立马执行的。。。
弯路3:异步问题经过探索后通过async和await解决了,但遇到导出时我们项目用的是layer,然而我找到的一个比较可信的excel插件被大量提及用layui调用,我强制又引入了layui虽然没有报错,但是还是导出不了,另外还看到有说这个插件在iframe中无法使用。。
最终解决方案
(1)异步问题:
经过上面的一系列探索,那么我就只剩下一个思路了,JavaScript中提供的async与await
async可以修饰一个方法为同步,await可以等待async修饰的方法的结果,那么这两个配合使用再结合传统的for循环就能胜任ajax分页批量请求问题了。
(2)导出excel问题:
当我打开excel插件文件中查看了代码,发现其全局有声明一个“LAY_EXCEL”的 变量,好吧,那么我直接用这个替换“layui”试试,结果果然成功了,并且目前也是在iframe中。
具体实施
当点击该导出按钮时,我先禁用当前按钮,防止再没有完成导出前重复点击,获取当前搜索条件下的最大页数(必须走一次后端,不能直接用页面上面的,因为当前页面是静态的已经通过上次进入列表时候渲染了的,但是此时用户可能在顶部搜索区域选择了下拉或者填写了搜索值),以及列表顶部的这些搜索参数,然后传参给具体导出的同步方法,该方法我声明了3个形参,一个是option就是搜索参数,option中的export为我后端区分是普通视图分页还是导出操作的,一个lastPage是最大页数,用于批量轮询请求直到请求队列结束,最后一个参数就是当前导出按钮,用于最终完成导出后恢复该导出按钮的禁用操作。
然后是在上面方法中调用了获取当前搜索条件下的总页数,当然同时也把导出的标题一起获取吧
接下来就是我的同步方法了,在同步方法中先初始化一个弹窗提示当前导出进度,每当一页请求完成就增加百分比,在同步方法中通过await来等待同步的promise方法,导出完成后关闭进度弹窗,并恢复导出按钮
最后就是promise实例方法和excel导出的方法了。
最后看看效果
最后附上源码及相关插件
关键字词:javascript,导出excel,promise,队列,promise.all,async,await
上一篇:过滤器(filters)
下一篇:全局过滤器