jQuery中首个done回调报错导致后续done回调无法执行的解决方案咨询
jQuery中首个done回调报错导致后续done回调无法执行的解决方案咨询
看起来你踩了jQuery 1.x版本Deferred的一个坑——当同一个Promise的done回调队列里有函数抛出未捕获的异常时,整个回调队列会直接中断,后面的回调就彻底跑不了了。而且这些回调是异步触发的(在Promise resolve时执行),你外层的try/catch根本抓不到这个错误,完全处于被动状态。
我给你几个贴合场景的可行思路,你可以根据实际情况选择:
方案1:自己包装独立Promise,和原队列彻底解耦
核心思路是:别直接监听原p3,自己新建一个Deferred,当原p3 resolve时手动触发自己的Deferred。这样你的回调和别人的回调不在同一个执行队列里,别人的错误完全影响不到你。
代码示例:
// 创建完全独立的Deferred,和原p3彻底切割 var myP3 = jQuery.Deferred(); // 监听原p3的状态,转发结果到自己的Deferred // 用then而非done,因为then的回调逻辑和原done队列是隔离的 p3.then(function(v3) { // 原p3成功就resolve自己的Deferred myP3.resolve(v3); }, function() { // 原p3失败也同步转发状态 myP3.reject.apply(myP3, arguments); }); // 你的init2里只监听自己的myP3 function init2() { jQuery.when(myP3).done(function (v3) { console.log("in init2 done"); // 现在一定会执行 }); }
这个方案的好处是彻底隔离,不管别人的代码怎么报错,你的回调都能正常触发——原p3的done队列错误只会影响它自己的回调链,不会波及then创建的新Promise。
方案2:全局捕获未处理异常,阻止执行中断
如果你的场景允许,可以通过全局错误捕获拦截别人代码抛出的异常,不让它终止整个回调队列的执行。
代码示例:
// 注册全局错误捕获 window.onerror = function(msg, source, line, col, error) { // 你也可以根据错误信息做过滤,只处理特定异常 // 返回true告诉浏览器:这个错误我处理了,别中断后续代码 return true; };
这个方案的缺点是会捕获所有全局未处理的错误,可能掩盖其他需要关注的问题,适合临时救急,不推荐作为长期方案。
方案3:轮询检查Promise状态(兜底方案)
如果上面两个方案都不适用,你可以用最粗暴但可靠的兜底方法:轮询原p3的状态,一旦发现它已经resolve,就直接执行你的回调。这种方法完全绕开原回调队列,肯定能触发你的代码。
代码示例:
function init2() { function myCallback(v3) { console.log("in init2 done"); } // 先检查p3是否已经resolve if (p3.state() === "resolved") { myCallback(); return; } // 未resolve就轮询检查状态 var checkTimer = setInterval(function() { if (p3.state() === "resolved") { clearInterval(checkTimer); myCallback(); } else if (p3.state() === "rejected") { clearInterval(checkTimer); // 这里可以处理p3失败的情况 } }, 50); // 每隔50ms检查一次,频率可自行调整 }
这个方案虽然不够优雅,但胜在绝对可靠——完全绕开了原回调队列的问题,只要p3最终resolve,你的回调就一定会执行。
备注:内容来源于stack exchange,提问作者devil_inside
相关产品推荐
相关产品推荐

