JQuery AJAX级联回调函数失效问题求助
问题分析与修复方案
我有三个关联的select组件,层级为 UnitType >> UnitSubType >> Unit,为减少冗余写了可复用的fetchItems函数填充数据。首次调用正常,但后续级联操作没触发,无报错,控制台打印了回调日志(---- Callback -----、Callback: fetchItems Next Type: UnitSubType)但实际没执行回调。
原函数代码
function fetchItems(type) { let apiurl let avail = '#available'; let callback = ''; let filter = ''; let filterValues = ''; let listID = '#hfSelected'; let json = '#json'; let nextType = ''; let select = '#selected'; switch (type) { case 'UnitType': apiurl = baseUnitTypesAPI + 0; avail += 'UnitTypes'; callback = 'fetchItems'; listID += 'UnitTypes'; json += 'UnitTypes'; nextType = 'UnitSubType'; select += 'UnitTypes'; break; case 'UnitSubType': apiurl = baseUnitSubTypesAPI + 0; avail += 'UnitSubTypes'; callback = 'fetchItems'; filterValues = $('#hfSelectedUnitTypes').val(); listID += 'UnitSubTypes'; json += 'UnitSubTypes'; //nextType = 'Unit'; select += 'UnitSubTypes'; filter = "{ UnitTypes: '" + filterValues + "'}"; case 'Unit': apiurl = baseUnitsAPI + 0; avail += 'Units'; filterValues = $('#hfSelectedUnitSubTypes').val(); listID += 'Units'; json += 'Units'; select += 'Units'; filter = "{ UnitSubTypes: '" + filterValues + "'}"; default: return; } //console.log('Type: ' + type); //console.log('API: ' + apiurl); //console.log('Available: ' + avail); //console.log('Callback: ' + callback); //console.log('Filter: ' + filter); //console.log('FilterValues: ' + filterValues); //console.log('ListID: ' + listID); //console.log('JSON: ' + json); //console.log('Next Type:' + nextType); //console.log('Select: ' + select); //console.log('-----------------------------------------------'); $.ajax({ url: apiurl, contentType: 'application/json; charset=utf-8', dataType: "json", data: (filterValues.length > 0) ? filter : '', type: (filterValues.length > 0) ? 'POST' : 'GET', beforeSend: function () { $(avail).empty(); $(select).empty(); }, success: function (data) { let selectedItems = $(listID).val().split(","); let newSelectedItems = []; $(json).val(data); $.each(JSON.parse(data), function (i, item) { if (selectedItems.includes(item.ID.toString())) { $(select).append(baseItem.replace('#ItemID', item.ID).replace('#ItemName', item.Name).replace('#ItemType', type)); newSelectedItems.push(item.ID) } else { $(avail).append($('<option>', { value: item.ID, text: item.Name })); } }); $(listID).val(newSelectedItems.join(',')); if (callback != '' && nextType != '') { console.log('---- Callback -----'); console.log('Callback: ' + callback + ' Next Type: ' + nextType) window[callback](nextType) } } }); }
核心问题原因
- switch分支缺失break:
case 'UnitSubType'和case 'Unit'末尾未添加break,导致执行完当前分支后会继续向下执行后续分支代码,最终走到default分支直接return,ajax请求根本没机会执行。 - 手动拼接JSON格式filter存在风险:若
filterValues包含特殊字符(如引号),会导致JSON格式错误。 - 回调用字符串引用不够严谨:字符串引用依赖全局作用域,直接使用函数引用更可靠。
修复后的代码
function fetchItems(type) { let apiurl; let avail = '#available'; let callback = fetchItems; let filter = {}; let filterValues = ''; let listID = '#hfSelected'; let json = '#json'; let nextType = ''; let select = '#selected'; switch (type) { case 'UnitType': apiurl = baseUnitTypesAPI + 0; avail += 'UnitTypes'; listID += 'UnitTypes'; json += 'UnitTypes'; nextType = 'UnitSubType'; select += 'UnitTypes'; break; case 'UnitSubType': apiurl = baseUnitSubTypesAPI + 0; avail += 'UnitSubTypes'; filterValues = $('#hfSelectedUnitTypes').val(); listID += 'UnitSubTypes'; json += 'UnitSubTypes'; //nextType = 'Unit'; select += 'UnitSubTypes'; if (filterValues) { filter.UnitTypes = filterValues; } break; case 'Unit': apiurl = baseUnitsAPI + 0; avail += 'Units'; filterValues = $('#hfSelectedUnitSubTypes').val(); listID += 'Units'; json += 'Units'; select += 'Units'; if (filterValues) { filter.UnitSubTypes = filterValues; } callback = null; break; default: return; } $.ajax({ url: apiurl, contentType: 'application/json; charset=utf-8', dataType: "json", data: Object.keys(filter).length > 0 ? JSON.stringify(filter) : '', type: Object.keys(filter).length > 0 ? 'POST' : 'GET', beforeSend: function () { $(avail).empty(); $(select).empty(); }, success: function (data) { let selectedItems = $(listID).val()?.split(",") || []; let newSelectedItems = []; $(json).val(data); $.each(JSON.parse(data), function (i, item) { const itemIdStr = item.ID.toString(); if (selectedItems.includes(itemIdStr)) { $(select).append(baseItem.replace('#ItemID', item.ID).replace('#ItemName', item.Name).replace('#ItemType', type)); newSelectedItems.push(itemIdStr); } else { $(avail).append($('<option>', { value: item.ID, text: item.Name })); } }); $(listID).val(newSelectedItems.join(',')); if (callback && nextType) { console.log('---- Callback -----'); console.log('Callback: fetchItems Next Type: ' + nextType); callback(nextType); } } }); }
修复点说明
- 给
case 'UnitSubType'和case 'Unit'添加break语句,确保每个分支执行完后跳出switch,避免提前return。 - 将filter改为对象存储,用
JSON.stringify转换为合法JSON字符串,避免特殊字符导致的格式错误。 - 回调直接使用函数引用
fetchItems代替字符串,调用时直接执行callback(nextType),比window[callback]更可靠。 - 处理
selectedItems为空的情况,避免split空值导致的异常。 - Unit作为最后一级,设置
callback = null,避免不必要的回调触发。
内容的提问来源于stack exchange,提问作者P S
相关产品推荐
相关产品推荐

