JS报错Uncaught TypeError: $(...).on(...).fail is not a function的原因及解决方法咨询
JS报错Uncaught TypeError: $(...).on(...).fail is not a function的原因及解决方法咨询
兄弟,我瞅了下你这段代码,一眼就定位到报错的根源了😎,下面给你拆解问题和修复方案:
一、报错核心原因
这个报错完全是因为你把fail()方法挂错了位置:
jQuery.on()是事件绑定方法,它返回的是jQuery DOM对象,这个对象根本没有fail()方法;fail()是jQuery Deferred(延迟对象)的专属方法,只有像AJAX请求这类返回Deferred/Promise的异步操作,才能链式调用fail()来处理失败回调;- 看你代码结构:你错误地把
fail()挂在了$('#jstree').on('loaded.jstree', ...)的后面,但它本来应该属于前面的_stocktakingSessionsService.getClassificationTree(1, 2)这个AJAX请求的回调链。
另外还发现两个小的选择器错误,也会导致DOM操作失效,顺便一起提了:
- 错误写法:
$(".modal-dialog modal-xl")→ 正确写法:$(".modal-dialog.modal-xl")(多类选择器之间必须用.连接,否则会被解析为后代选择器) - 错误写法:
$(".content d-flex flex-column flex-column-fluid")→ 正确写法:$(".content.d-flex.flex-column.flex-column-fluid")
二、修复后的完整代码
(function ($) { app.modals.ClassificationTreeModal = function () { var selectedId = []; var _stocktakingSessionsService = abp.services.app.stocktakingSessions; var _modalManager; this.init = function (modalManager) { _modalManager = modalManager; var modal = _modalManager.getModal(); // 修复选择器错误:多类选择器用.连接 $(".modal-dialog.modal-xl") .removeClass("modal-dialog modal-xl") .addClass("modal-dialog modal-xl modal-dialog-scrollable"); // 修复选择器错误 $(".content.d-flex.flex-column.flex-column-fluid") .removeClass("content d-flex flex-column flex-column-fluid") .addClass("modal-body"); // 把fail()移到AJAX请求的链式调用中 _stocktakingSessionsService.getClassificationTree(1, 2) .done(function (data) { var res1 = JSON.parse(data); $('#jstree').jstree({ core: { data: res1, check_callback: true, "themes": { "variant": "large" } }, "types": { "default": { "icon": "fa fa-folder text-primary" }, "file": { "icon": "fa fa-folder text-primary" } }, 'checkbox': { //keep_selected_style: false, ////whole_node: false, ////tie_selection: true //three_state: false, //cascade: 'none' }, 'search': { 'case_insensitive': true, 'show_only_matches': true }, "plugins": ["search", "wholerow", "checkbox"] }).on('search.jstree', function (nodes, str, res) { if (str.nodes.length === 0) { $('#jstree').jstree(true).hide_all(); } }); $('#deliverable_search').keyup(function () { $('#jstree').jstree(true).show_all(); $('#jstree').jstree('search', $(this).val()); }); $('#jstree').on('changed.jstree', function (e, data) { selectedId = [] for (var i = 0; i < data.selected.length; i++) { selectedId.push(data.instance.get_node(data.selected[i]).id); } }); var inputString = document.getElementById('arrayInput').value; var nodesToCheck = JSON.parse(inputString); $('#jstree').on('loaded.jstree', function () { // Check the node with id '2' nodesToCheck.forEach(function (nodeId) { $('#jstree').jstree('check_node', nodeId.toString()); }); }); }) // 这里才是fail()的正确位置 .fail(function (err) { console.error('获取分类树数据失败:', err); abp.notify.error(app.localize('FailedToLoadData')); }); }; this.save = function () { var arr = selectedId var data = { arr2: selectedId, }; _modalManager.setResult(data); abp.event.trigger('app.ClassificationTreeStocktakingSessionModalSaved', data); abp.notify.info(app.localize('SavedSuccessfully')); _modalManager.close(); }; } })(jQuery);
三、额外小提醒
- 以后写链式调用的时候,一定要搞清楚每个方法返回的对象类型:
- DOM操作/事件绑定方法 → 返回jQuery对象,只能调用jQuery的DOM相关方法
- AJAX/异步操作 → 返回Deferred/Promise对象,才能用
done()/fail()/then()这类异步回调方法
- 你的jstree配置里,
checkbox的注释代码可以根据实际需求开启,比如如果不需要父子级联动,就打开three_state: false和cascade: 'none',避免不必要的选中逻辑问题。
这样应该就彻底解决你的报错,也修复了潜在的其他小问题😉




