本帖最后由 dexteryao 于 2021-4-25 10:56 编辑
SpreadJS提供了异步函数的功能,可以让函数通过调用API异步获取数据。但是当页面上使用的异步函数较多,刷新计算时会同时发生大量的网络请求,不仅给服务器造成压力,也会由于异步函数的同时更新造成页面的频繁刷新,影响用户体验。
为了解决这个问题,我们可以采用请求堆栈的方式,收集函数请求,统一发送网络请求并一次更新。
具体更新时机机制可以根据我们业务需求决定,下面以定时请求为例说明具体实现。
当第一个请求发生1秒后,发起一次网络请求。1秒内有其他请求进入就收集进堆栈,后续请求放入下一个堆栈,以此类推。
下面代码是一个普通异步函数GETNUMBERFROMSERVER的实现,调用getData接口(模拟接口直接返回arg1数据,未做其他处理),传递参数,获取显示内容并展示在单元格。
- var GetNumberFromServer = function () {
- };
- GetNumberFromServer.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction("GETNUMBERFROMSERVER", 1, 2);
- GetNumberFromServer.prototype.evaluate = function (context, arg1, arg2) {
- fetch("/spread/getData?data="+arg1)
- .then(function(response) {
- return response.text();
- })
- .then(function(text) {
- context.setAsyncResult(text);
- });
- };
- GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("GETNUMBERFROMSERVER", new GetNumberFromServer());
复制代码
为了减少请求,我们使用一个缓存对象存放请求数据,定时调用接口处理
- let callStack = {}; //收集请求数据
- let callingStack = {}; //缓存正在请求中的数据信息
- let callStackCount = 0; //请求数量,当作请求ID,用于区分请求内容
- let timingId = 0; //用于判断当前是否有定时器等待请求中
复制代码
定义请求方法,代替再函数中直接调用API接口
- // data 请求数据
- // context 异步函数context, 网络请求结束后回调时使用
- // callback 回调函数
- function stackCall(data, context, callback){
- let id = callStackCount++;
- callStack[id] = {};
- callStack[id].data = data;
- callStack[id].context = context;
- callStack[id].callback = callback;
- if(timingId === 0){ // 同时只有一个定时器
- timingId = setTimeout(function(){
- callingStack = callStack;
- callStack = {};
- let newData = "" //合并请求数据,根据实际业务情况整理
- for(let cId in callingStack){
- newData += (cId + "," + callingStack[cId].data + ";");
- }
- // 发送请求,这里模拟数据,发送什么返回什么
- fetch("/spread/getData?data=" + newData)
- .then(function(response) {
- return response.text();
- })
- .then(function(text) {
- let resData = newData.split(";");
- let spread = designer.getWorkbook();
- spread.suspendPaint(); //暂定页面绘制
- //解析返回的数据
- for(let resId in resData){
- if(resData[resId]){
- let ress = resData[resId].split(",");
- // 根据Id,获取函数的context,调用callback回调
- callingStack[ress[0]].callback.call(null, callingStack[ress[0]].context, ress[1])
- }
- }
- spread.resumePaint(); //重启统一绘制
- timingId = 0;
- });
- }, 1000)
- }
- }
复制代码
更新异步函数实现方式,函数中调用stackCall堆栈函数,批量调用成功后执行callback回调中的setAsyncResult方法。
- GetNumberFromServer.prototype.evaluate = function (context, arg1, arg2) {
- stackCall(arg1, context, function(context, text){
- context.setAsyncResult(text);
- })
- };
复制代码
通过以上实现,当页面有大量异步请求时会统一处理,一次刷新。
另外还可以使用doNotRecalculateAfterLoad导入选项,在首次加载时不计算,使用json中原始值,以及calcOnDemand开启按需计算。
这两个option可以根据您的实际需求设置。
- json.calcOnDemand = true;
- spread.fromJSON(json, { doNotRecalculateAfterLoad: true });
复制代码
|
|