上传含2000+行的Excel文件构建HTML表格时触发SIGILL错误求助
大体积Excel数据构建HTML表格时触发SIGILL错误
我有一个通过XMLHttpRequest上传Excel文件并返回JSON数据的脚本,小文件处理完全正常。但上传2000+行的Excel文件时,上传流程正常,浏览器直接输出JSON也没问题,但用该数据构建HTML表格时出现Error code: SIGILL错误。
操作流程
- 选择文件并通过XMLHttpRequest上传
- 将返回的response对象传入JavaScript函数构建表格
相关代码
function tableBuild(productsJSON) { var itemsListHtml = '<table class="table table-striped table-hover mx-0 my-0 py-0 px-0 items-table" style="position:relative;">'; itemsListHtml += '<thead style="position: sticky;top: 0" class="table-dark">'; itemsListHtml += '<tr>'; itemsListHtml += '<th scope="col">#</th>'; itemsListHtml += '<th scope="col"><?= Text::get('Title'); ?></th>'; itemsListHtml += '</tr>'; itemsListHtml += '</thead>'; itemsListHtml += '<tbody id="itemsListHtml">'; $.each(productsJSON.Products,function(i,v) { itemsListHtml += '<tr>'; itemsListHtml += '<td class="transition">'+parseInt(i+1)+'</td>'; itemsListHtml += '<td class="transition"><input type="text" data-label="product_title" name="product_title['+i+']" value="'+v.title+'" /></td>'; itemsListHtml += '<tr>'; // 此处存在语法错误,应为</tr> }); itemsListHtml += '</tbody>'; itemsListHtml += '</table>'; }
截取后的JSON数据示例(原数据含2000+条目)
{ "responseData":{"Products":[ {"id":null,"add_class":null,"error":null,"type_id":"1","title":"POCO X5 Pro 5G 8GB/256GB Blue EU (22101320G)","type_title":"Serial","serial":"8.6916806567786E+14","qty":1,"measure_unit_id":1,"measure_unit_title":"pcs","unit_price":289,"total_price":289}, {"id":null,"add_class":null,"error":null,"type_id":"1","title":"POCO X5 Pro 5G 8GB/256GB Blue EU (22101320G)","type_title":"Serial","serial":"8.6916806695989E+14","qty":1,"measure_unit_id":1,"measure_unit_title":"pcs","unit_price":289,"total_price":289}, {"id":null,"add_class":null,"error":null,"type_id":"1","title":"POCO X5 Pro 5G 8GB/256GB Blue EU (22101320G)","type_title":"Serial","serial":"8.6916806695999E+14","qty":1,"measure_unit_id":1,"measure_unit_title":"pcs","unit_price":289,"total_price":289}, {"id":null,"add_class":null,"error":null,"type_id":"1","title":"POCO X5 Pro 5G 8GB/256GB Blue EU (22101320G)","type_title":"Serial","serial":"8.6916806696022E+14","qty":1,"measure_unit_id":1,"measure_unit_title":"pcs","unit_price":289,"total_price":289}, {"id":null,"add_class":null,"error":null,"type_id":"1","title":"POCO X5 Pro 5G 8GB/256GB Blue EU (22101320G)","type_title":"Serial","serial":"8.691680669904E+14","qty":1,"measure_unit_id":1,"measure_unit_title":"pcs","unit_price":289,"total_price":289 } ] } }
排查与解决方向
1. 修复代码语法错误
循环内最后一行的标签闭合错误:itemsListHtml += '<tr>'; 应为 itemsListHtml += '</tr>';。小数据量时浏览器可容错,但大数据量下畸形HTML会触发DOM解析异常,甚至导致引擎崩溃(SIGILL通常关联非法指令执行)。
2. 优化字符串拼接方式
当前用单字符串拼接2000+行HTML,会生成超大型字符串对象,既占用内存又增加DOM解析压力。推荐两种优化方式:
- 用数组存储片段后拼接:
function tableBuild(productsJSON) { var itemsListHtml = [ '<table class="table table-striped table-hover mx-0 my-0 py-0 px-0 items-table" style="position:relative;">', '<thead style="position: sticky;top: 0" class="table-dark">', '<tr>', '<th scope="col">#</th>', '<th scope="col"><?= Text::get('Title'); ?></th>', '</tr>', '</thead>', '<tbody id="itemsListHtml">' ]; $.each(productsJSON.Products,function(i,v) { itemsListHtml.push( '<tr>', '<td class="transition">'+parseInt(i+1)+'</td>', '<td class="transition"><input type="text" data-label="product_title" name="product_title['+i+']" value="'+v.title+'" /></td>', '</tr>' ); }); itemsListHtml.push('</tbody>', '</table>'); var finalHtml = itemsListHtml.join(''); // 后续插入DOM逻辑 } - 用DocumentFragment分批构建DOM:
function tableBuild(productsJSON) { var table = document.createElement('table'); table.className = 'table table-striped table-hover mx-0 my-0 py-0 px-0 items-table'; table.style.position = 'relative'; var thead = document.createElement('thead'); thead.className = 'table-dark'; thead.style.position = 'sticky'; thead.style.top = '0'; var headerTr = document.createElement('tr'); var th1 = document.createElement('th'); th1.scope = 'col'; th1.textContent = '#'; var th2 = document.createElement('th'); th2.scope = 'col'; th2.textContent = '<?= Text::get('Title'); ?>'; headerTr.appendChild(th1); headerTr.appendChild(th2); thead.appendChild(headerTr); table.appendChild(thead); var tbody = document.createElement('tbody'); tbody.id = 'itemsListHtml'; $.each(productsJSON.Products,function(i,v) { var tr = document.createElement('tr'); var td1 = document.createElement('td'); td1.className = 'transition'; td1.textContent = parseInt(i+1); var td2 = document.createElement('td'); td2.className = 'transition'; var input = document.createElement('input'); input.type = 'text'; input.dataset.label = 'product_title'; input.name = 'product_title['+i+']'; input.value = v.title; td2.appendChild(input); tr.appendChild(td1); tr.appendChild(td2); tbody.appendChild(tr); }); table.appendChild(tbody); // 插入到目标容器 document.getElementById('target-container').appendChild(table); }
3. 排查SIGILL深层原因
SIGILL错误表示浏览器引擎执行了非法指令,可能的触发点:
- 浏览器版本过旧,存在超大DOM/字符串处理bug,升级浏览器测试;
- 内存不足导致引擎崩溃,DOM构建的内存占用远高于JSON本身;
- 浏览器扩展干扰渲染,切换到无痕模式测试。
4. 考虑虚拟滚动/分页
若必须展示全部2000行,可实现虚拟滚动(仅渲染可视区域内的行),避免一次性加载所有DOM节点。
内容的提问来源于stack exchange,提问作者Felix Abdullayev
相关产品推荐
相关产品推荐

