DataTables显示[object promise]而非真实数据问题求助
解决DataTables中显示
[object promise]而非实际测试名称的问题 你的问题根源在于DataTables的render函数不支持异步返回值:async函数的返回本质是一个Promise对象,DataTables会直接把这个对象转换成字符串[object promise]显示,不会等待Promise完成后再渲染最终值。虽然你在console.log里能看到正确结果,但那是Promise resolve后的输出,和DataTables的渲染时机不匹配。
下面提供两种可行解决方案:
方案1:预加载并整合数据(推荐,性能更优)
先获取所有测试分类数据,批量获取对应的测试名称并整合,再将处理好的数据传给DataTables,避免在渲染阶段做异步请求:
$(document).ready(async function () { // 1. 获取TestCategory基础数据 const categoryResponse = await $.ajax({ url: "https://localhost:7136/api/TestCategory", type: "GET", dataType: "json" }); const categoryData = categoryResponse.data; // 2. 收集所有需要查询的测试ID并去重,减少重复请求 const allTestIds = []; categoryData.forEach(item => { item.testKit.split(',').forEach(id => { if (!allTestIds.includes(id)) allTestIds.push(id); }); }); // 3. 并行请求所有测试名称,提升请求效率 const testNamePromises = allTestIds.map(id => $.ajax({ url: `https://localhost:7136/api/Test/${id}`, type: "GET", dataType: "json" }).then(res => ({ id, name: res.data.testName })) ); const testNameMap = await Promise.all(testNamePromises); // 转成键值对,方便快速查找 const testNameLookup = testNameMap.reduce((map, item) => { map[item.id] = item.name; return map; }, {}); // 4. 整合数据,把testKit字段替换为对应的名称字符串 categoryData.forEach(item => { item.testKitNames = item.testKit.split(',').map(id => testNameLookup[id]).join(','); }); // 5. 初始化DataTables,直接使用整合后的字段 table = $('#TblTestCategory').DataTable({ "order": [], "drawCallback": function (settings) { var api = this.api(); var startIndex = api.context[0]._iDisplayStart; var counter = startIndex + 1; api.column(0, { page: 'current' }).nodes().each(function (cell, i) { cell.innerHTML = counter; counter++; }); }, responsive: true, data: categoryData, "columns": [ { "data": "testKitNames", "orderable": false, "orderData": [1] } // 其他列配置... ] }); });
方案2:在render中手动更新单元格(适合小数据量场景)
如果不想修改初始数据加载逻辑,可以在render里发起异步请求,等Promise完成后手动更新单元格内容,同时避免返回Promise:
$(document).ready(function () { table = $('#TblTestCategory').DataTable({ "order": [], "drawCallback": function (settings) { var api = this.api(); var startIndex = api.context[0]._iDisplayStart; var counter = startIndex + 1; api.column(0, { page: 'current' }).nodes().each(function (cell, i) { cell.innerHTML = counter; counter++; }); }, responsive: true, "ajax": { url: "https://localhost:7136/api/TestCategory", type: "GET", "dataType": "json", "dataSrc": "data", }, "columns": [ { "data": "testKit", "orderable": false, "orderData": [1], "render": function (data, type, row, meta) { // 先显示加载提示,避免显示[object promise]或空白 const cell = $(table.cell(meta.row, meta.col).node()); cell.text('加载中...'); // 异步获取名称后更新单元格 generateString(data).then(testName => { cell.text(testName); }); // 返回空字符串,不要返回Promise return ''; } } // 其他列配置... ] }); const generateString = async (input) => { const arr = input.split(','); // 用Promise.all并行请求,替代循环await提升性能 const testNamePromises = arr.map(number => $.ajax({ url: `https://localhost:7136/api/Test/${number}`, type: 'GET', contentType: "application/json; charset=utf-8", dataType: "json" }).then(res => res.data.testName) ); const testNames = await Promise.all(testNamePromises); return testNames.join(','); }; });
额外优化说明
- 两种方案都将原循环
await请求改为Promise.all并行请求,大幅减少请求等待时间,提升页面加载效率。 - 方案1的预加载方式更适合数据量较大的场景,能避免渲染阶段的异步请求阻塞和重复请求问题。
内容的提问来源于stack exchange,提问作者Bayu Pratama
相关产品推荐
相关产品推荐

