回调函数错误写法的报错总结

本文介绍了一种通过用户选择动态加载地图JS并渲染地图的方法。利用jQuery改变事件获取用户选择,通过创建script元素动态引入对应的地图JS文件,然后调用回调函数进行地图渲染。文章展示了如何避免错误的回调调用方式,确保地图正确加载和显示。


 
    var provinces=['xizang','beijing','china'],
        provincesText=['西藏','北京','中国'],
        placeCode=[540000,110000],
        mapType = "北京", //地图类型
        EpidemicDynActiveClass = 0 //疫情K线趋势图类型       
 
        $("#selectMap").change(function(){
            var val = $("#selectMap").val(); //获取Select选择的Value
            loadScriptMap(val,renderMap);
            //loadScriptMap(val,renderMap());  //错误写法,会导致报错callback is undefined
        })
 
        function loadScriptMap(name,callback){
            // 获取这个省的拼音名字 name = '四川' => pinyinName = 'sichuan'
            let pinyinName = provinces[provincesText.indexOf(name)]
            // 引入这个对应的地图JS,如果是在项目中要打包,请将这些文件提取出来,放在静态资源中
            // build的时候这些文件不会被打包,无可加载资源地图是不会显示的!!!!
            var ele= document.createElement("script");
            ele.setAttribute("type", "text/javascript");
            // 根据用户选择的地图类型,动态引入
            ele.setAttribute("src", "../../assets/lib/map/china.js")
            document.body.appendChild(ele)
            callback(name,EpidemicDynActiveClass)
        }    
 
        function renderMap(Type,activeClass){
            dosomething()
        }
 

<think> 我们正在讨论的是Vue.js中Element UI表单验证的问题。根据引用内容,`this.$refs.form.validate`方法是一个基于回调的函数,它不会返回Promise。因此,如果你试图在async函数中使用await来等待它的结果,会导致回调不执行(因为await需要等待一个Promise,而这里没有返回Promise)。 引用[1]说明了这个方法本身是通过回调函数来传递验证结果的,与async/await不兼容。 引用[2]提到用户遇到了回调不执行的问题,并且提到可能是因为自定义校验规则没有正确调用回调函数(即每个自定义规则都必须调用cb()来继续验证流程)。 引用[3]给出了一个自定义校验规则的例子,并指出在自定义校验规则中,不论校验是否通过,都必须调用cb(),否则会导致整个验证流程挂起,从而造成回调不执行。 因此,解决这个问题的关键点在于: 1. 检查自定义校验规则(如果有的话)是否在每一个分支都调用了cb()。 2. 避免在async函数中使用await来等待这个验证结果,因为validate方法不返回Promise。 解决方案: 1. 如果没有自定义校验规则,则检查表单的ref命名是否正确,以及确保已经正确绑定了rules。 2. 如果有自定义校验规则,请确保在自定义规则的每一个逻辑分支都调用了cb(),包括成功和失败的情况。例如,在引用[3]的例子中,他们在最后添加了cb()以确保调用,但注意这可能导致即使前面有错误也会被忽略(因为cb()被调用了两次)。正确的做法是在每个分支都调用一次cb(),且只调用一次。 根据引用[3]的例子,我们发现他们在自定义规则中,当比例和不等于100时,调用cb(new Error('...')),然后后面又调用了一次cb()(不带参数表示验证通过)。这会导致两次调用,而第二次调用会覆盖前面的错误,所以即使有错误也会变成通过。因此,应该去掉后续的cb(),改为: changeRewardRatio(rule, val, cb) { const num_count = this.claimDialogForm.saveList.reduce((pre, cur) => { return pre + cur.rewardRatio; }, 0); if (num_count !== 100) { cb(new Error('比例累计之和需等于100')); } else { // 验证通过,清除该字段的错误信息(如果需要的话,也可以不调用clearValidate,因为通过时cb()不带参数即可) // 注意:在自定义规则中,不应该调用clearValidate,因为验证过程是由表单统一管理的,我们只需要在这里给出结果即可。 cb(); // 表示验证通过 } } 另外,注意在自定义规则中,如果使用了异步操作,需要保证在异步操作完成后调用cb()。 3. 如果不需要使用async/await,则直接使用回调函数的方式。 4. 如果需要将validate转换为Promise,可以自己封装一个Promise,例如: const validateForm = () => { return new Promise((resolve, reject) => { this.$refs.form.validate(valid => { if (valid) { resolve(); } else { reject(new Error('表单验证失败')); } }); }); }; 然后在async函数中使用await: async function submit() { try { await validateForm(); // 验证通过,提交表单 } catch (e) { // 验证失败 } } 但是注意,如果自定义校验规则中有错误(比如没有调用cb),那么validate的回调将永远不会被调用,导致这个Promise一直处于pending状态。因此,确保自定义规则正确调用cb是关键。 综上所述,针对回调未执行的问题,主要检查点: - 表单的ref是否正确(确保this.$refs.form访问到的是表单实例) - 表单的model和rules是否绑定正确 - 自定义校验规则中是否每个分支都调用了cb(),且只调用一次 - 避免在自定义校验规则中调用clearValidate(因为验证过程中应该由表单自身管理) - 如果需要在async/await中使用,请封装成Promise,同时确保上述规则正确。 因此,解决步骤: 1. 检查自定义校验规则,确保每个分支都调用了cb(),且只调用一次。 2. 如果没有自定义校验规则,检查ref、model、rules等基本配置。 3. 如果还是不行,检查是否有其他因素(比如表单字段的prop是否与rules中的字段对应,或者动态表单字段变更后是否触发了重新渲染等)。 根据引用[2]的经验,有时候可能是因为样式修改导致的问题,但这种情况较少见,主要关注校验规则的编写。 </think> 针对 `this.$refs.form.validate` 不报错且回调未执行的问题,以下是关键原因和解决方案,结合引用内容分析: --- ### **主要原因** 1. **自定义校验规则未调用回调函数**(核心问题) - 引用[3] 显示:若自定义校验规则(如 `changeRewardRatio`)的分支逻辑中**未调用 `cb()`**,会导致整个验证流程阻塞。 - 典型错误:校验失败时调用 `cb(new Error(...))`,但成功分支**遗漏 `cb()`**,或异步操作未正确触发回调。 2. **回调与 async/await 冲突** - 引用[1] 指出:`.validate` 是**基于回调**的方法,本身**不返回 Promise**。在 `async` 函数中使用 `await this.$refs.form.validate()` 会导致回调无法执行。 3. **Element UI 表单配置问题** - 表单 `ref` 名称错误(如 `this.$refs.formDom` 误写为 `this.$refs.form`)。 - 未正确绑定 `rules` 或 `model`,或动态表单字段未触发更新。 --- ### **解决方案** #### ✅ 1. **检查自定义校验规则** - **确保每个逻辑分支都调用 `cb()`**,包括成功和失败情况: ```javascript customRule(rule, value, cb) { if (value === valid) { cb(); // 必须调用!否则阻塞流程 } else { cb(new Error("错误信息")); } } ``` - **禁止重复调用 `cb()`**(如引用[3]的 `cb()` 被调用两次),每个规则仅调用一次。 #### ✅ 2. **避免 async/await 误用** - **改用回调函数**: ```javascript // 正确写法 this.$refs.form.validate((valid) => { if (valid) { /* 通过 */ } else { /* 失败 */ } }); ``` - **如需 Promise 封装**: ```javascript const validateForm = () => new Promise((resolve) => { this.$refs.form.validate(resolve); }); // 使用 validateForm().then(valid => { ... }); ``` #### ✅ 3. **检查表单基础配置** - **确认 `ref` 命名一致性**: ```vue <el-form ref="form"> <!-- 确保此处 ref 与代码一致 --> ``` - **动态表单需触发更新**: 修改表单字段后,调用 `this.$nextTick(() => this.$refs.form.validate())`。 #### ✅ 4. **排查 Element UI 版本问题** - 升级 Element UI 至最新版(历史版本存在回调不执行的 Bug)。 - 检查是否覆盖了关键样式(引用[2]),避免影响验证逻辑。 --- ### **调试步骤** 1. 检查浏览器控制台是否有 **JS 执行错误**(如未捕获的异常)。 2. 在自定义规则中添加 `console.log`,确认是否进入规则函数。 3. 简化表单:移除自定义规则后验证是否正常,逐步定位问题规则。 > **关键提示**:90% 的问题源于**自定义校验分支未调用 `cb()`**(如引用[3])。务必确保每个路径都有回调![^3] --- **相关问题** 1. Element UI 表单校验规则如何动态更新? 2. 如何全局封装 Element UI 的表单验证逻辑? 3. Vue 3 + Element Plus 的表单验证有何差异?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值