Tableau JavaScript同步调用问题:异步函数未完成就进入下一轮循环
问题分析
你的核心问题在于**Send_Tablo函数内的所有异步操作(比如changeParameterValueAsync、getSummaryDataAsync)都是非阻塞的**,而你原本的循环是同步执行的——它不会等待当前Send_Tablo里的异步任务完成,就立刻触发下一次调用,导致多个异步请求同时跑,数据被后续请求覆盖,最终拿到的不是对应请求的结果。
解决方案
要解决这个问题,我们需要做两个关键改造:
- 让
Send_Tablo函数返回一个「完成信号」(Promise),确保所有异步操作执行完毕后才标记函数完成; - 将同步循环改成异步循环,每次循环都等待当前
Send_Tablo的所有操作完成后,再执行下一轮。
1. 改造Send_Tablo为异步函数
我们用async/await语法重构函数,让所有异步操作按顺序执行,并且函数执行完所有逻辑后才会结束:
async function Send_Tablo(filterValfscr) { var filter_indx = JSON.parse(window.localStorage.getItem('filter_indx')); var arry = []; for (var i = 0; i < filter_indx.s_filter_i.length; i++) { Attr_lab_name = filter_indx.s_filter_i[i].ATTRIBUTELABEL; arry.push(filter_indx.s_filter_i[i].VALUE); } // 等待参数修改完成 await currentViz.getWorkbook().changeParameterValueAsync('Attribute_Label', filterValfscr, Attr_lab_name, arry); alert(filterValfscr); // 等待第一次数据获取完成 const sheet = currentViz.getWorkbook().getActiveSheet(); const dataResult = await sheet.getSummaryDataAsync(options); const data = dataResult.getData(); console.log("Data", data); // 等待内部的frscr_demo所有异步操作完成 await frscr_demo(); // 把内部函数也改成异步,确保它的操作也按顺序完成 async function frscr_demo() { // 等待过滤规则应用完成 await currentViz.getWorkbook().getActiveSheet().applyFilterAsync(Attr_lab_name, arry, tableau.FilterUpdateType.REPLACE); const fscrSheet = currentViz.getWorkbook().getActiveSheet(); // 等待FSCR数据获取完成 const fscrResult = await fscrSheet.getSummaryDataAsync(options); const fScr_data = fscrResult.getData(); console.log("FSCR", fScr_data); const aa = $(fScr_data).length; } }
2. 改造循环为异步循环
把循环放在一个异步函数里,用await等待每一次Send_Tablo执行完成,再进入下一轮:
async function processFiltersSequentially() { const checkLen = $s_filter_i.length; for (let i = 0; i < checkLen; i++) { const filterValfscr = $s_filter_i[i].VALUE; // 强制等待当前Send_Tablo的所有异步操作完成,再执行下一次 await Send_Tablo(filterValfscr); } } // 启动顺序处理 processFiltersSequentially();
关键说明
async/await语法让异步代码看起来像同步代码,确保每一步操作都等待前一步的异步任务完成后再执行;- 把
frscr_demo也改成异步函数并使用await,是因为它内部也有applyFilterAsync和getSummaryDataAsync两个异步操作,必须确保它们执行完毕后,整个Send_Tablo才算真正完成; - 循环改用
let i而不是var i,避免循环变量的作用域问题(var会导致循环结束后所有异步回调共享同一个i值)。
内容的提问来源于stack exchange,提问作者Prasad A U
相关产品推荐
相关产品推荐

