jQuery使用JSONP时无法捕获错误

72 阅读2分钟

又是对着老项目修修补补的一天...

发发牢骚

测试反馈说一直无法获取最新的软件版本,对于这种几年没动过、也没客户反馈问题的功能,很自然的反应就是,交付那边不支持这款设备~

但是较真的测试却直接拉会打破了平静的一天,结果云交付的一句:升级补丁功能根本不支持啊,为什么要去获取?也直接让我大跌眼镜。而导师那边说该功能是有做失败处理的,按理应该会有显示。(合着都默认忽视这个问题了呗?之前还测试是通过了?)

image.png 好吧,既然这样我们就来看看原因吧。

故障背景

这个地方其实是使用JSONP来查询是否有 最新版本的升级包推荐的升级补丁

什么?你还不知道什么是JSONP?那来看看我的另一篇文章吧👉(一文带你理解同源、跨域、JSONP、CORS)

不看也没事的,老技术不需要了解,你可能以后也用不上😥

而代码的处理逻辑大体是这样:dao 返回两个 $.getJson 方法(分别是获取软件版本和获取升级补丁),然后通过 $.when(ajax1, ajax2).done.fail 来分别进行成功后的操作和失败操作。

    var ajax1 = CLI.getCloudApVers([data]);  // 获取软件版本
    var ajax2 = CLI.getCloudPatchVers(data);   // 获取补丁
    $.when(ajax1, ajax2).done(function(res01, res02) {
        // 进行成功操作
    }).fail(function () {
        // 进行失败操作
    });

而通过打断点会发现,无论如何都进不去成功操作和失败操作之中。

分析原因

通过观察获取升级补丁的接口回显,可以明显发现似乎和成功的接口返回不一致!

成功的👇 img_v3_02gk_f1540093-0fcd-4765-8515-2eb315d74eeg.jpg

失败的👇 img_v3_02gk_6138627d-657c-4e72-8221-a93933de65ag.jpg

而且失败接口的 $.getJson 返回值的 readyState 值一直是 1

img_v3_02gk_b89c26a6-b51d-4080-b8fe-faf7742a8eeg.jpg

通过不停的搜索和浏览,最终我们可以确定原因:

  1. 由于云交付暂时不支持获取补丁版本,返回的数据格式不是JSON;
  2. 而jQuery 1.11.x(代码使用1.11.3 )使用.onreadystatechange来跟踪jsonp请求何时返回;👉(getJSON .fail没有捕获错误 - Thinbug)
  3. 发送脚本或jsonp请求时,无法跟踪超时错误以外的错误(readyState一直是1);

正是以上三点原因叠加导致了我们代码根本无法通过$.when(ajax1, ajax2).done.fail来捕获失败!

😫😫什么永远无法触及的失败啊?!

故障修订

感谢这篇文章提供的参考,我也是通过这个方法进行修订的。而且这篇文章写的非常通俗易懂且详细。👉(解决jQuery使用JSONP时产生的错误_jquery_脚本之家 (jb51.net))

这边我也附上我的简单修订,因为只是针对获取补丁失败进行修订,所以只需要判断src是否是获取补丁的链接即可。

    var head = document.head || $('head')[0] || document.documentElement;
    var script = $(head).find('script')[0];
    // 由于云交付暂时不支持获取补丁版本,返回的数据格式不是JSON导致jQuery无法捕获失败
    // 在这里通过该方法捕获失败
    script.onerror = function (evt) {
        var src = script.src.toString() || '';
        // 判断是不是获取补丁
        if (src.includes('getPatchRecommend')) {
            // 失败时的操作
        }
    };

太长了不想看?

由于云交付暂时不支持获取补丁版本,返回的数据格式不是JSON;而jQuery 1.11.x(代码使用1.11.3 )使用.onreadystatechange来跟踪JSONP请求何时返回。因此,在发送脚本或JSONP请求时,无法跟踪超时错误以外的错误(readyState一直是1);导致jQuery无法通过.fail捕获失败