解决umi.js或dva.js中effect函数发生错误dispatch失效的问题

问题背景

在项目的model文件中,通常在effect中进行网络请求等异步操作,当网络错误或者请求结果错误时,以及代码语法错误时,无论是否主动使用throw语句抛出错误,下一次再调用dispatch访问effect中的函数时,均会失效。

问题复现

  1. 编辑完表单后通过dispatch 访问model中effects中的edit函数
    在这里插入图片描述
  2. edit 方法中进行网络请求,更新表单数据等操作
    在这里插入图片描述
  3. 此时发生了网络错误,或者服务端异常,返回5xx状态的错误结果。控制台的打印结果为:
    在这里插入图片描述
    此时系统界面上的表现一切正常,加载状态正常结束,页面提示也正常,理论上等待网络或者服务器正常之后再次点击按钮,重新执行一遍流程就能返回正常结果
  4. 但是,结果如下
    在这里插入图片描述
    dispatch函数没有成功执行,甚至都没有进入到effects的edit函数中,也没有发起网络请求,界面发生了死锁。
    而且经过测试,此时访问其他的effects函数同样会失效,但是能够正常访问reducers函数。
  5. 总结一下,错误的发生条件:
    1)effects函数中发生错误,但是没有捕获。
    2)捕获错误之后,使用throw关键字抛出。(不抛出就没问题)

原因分析

在问题复现的第三步中,有两个值得注意的输出:

  1. 第一个是dispatch 的返回值,是一个pending 状态的promise对象,而且经过测试在这个dispatch之后使用.then/.catch 都不能正常运行。而在effect函数正常执行时,这个返回的promise对象的状态是fulfilled
    在这里插入图片描述
    由此推测,dispatch 失效的原因应该是 umi/dva 在dispatch实现的时候做了错误的兜底捕获,并在发生这种未捕获的错误时改变自身的状态,并在下一次被调用时阻止调用。then方法无法执行的原因应该也是内部做了二次封装,返回的对象并不是一个典型的promise对象。但这些都是主观推测,等有空了研究下dispatch的源码。
  2. 另一个值得注意的是最后输出的一段奇怪的报错信息,明显与正常的js代码报错不同:
    在这里插入图片描述
  3. 反思了下项目的设计,在发生错误或者抛出错误之后,没有做全局错误的兜底捕获,这明显是不对的,很有可能造成项目的崩溃,而且也不方便错误的定位。

解决方法

搜索上诉的报错信息发现有现成的解决方案:
umi项目中报错uncaught at _callee3 at _calle3
其他解决方案:
使用dva中函数,如果返回错误结果,再次调用,dispatch无响应
总结一下,主要有两个方案:

  1. 使用try...catch... 主动捕获可能发生错误的代码,并进行手动处理,不要使用 throw 再次抛出。
  2. 使用 dva 框架自带的 onError 全局错误管理函数,捕获错误并处理。

Dva文档中的描述:
在这里插入图片描述
Umi文档中的描述:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值