【问题标题】:JS exception is still able to sneak in but very rarely, not sure whyJS 异常仍然能够潜入,但很少,不知道为什么
【发布时间】:2015-09-12 04:21:46
【问题描述】:

我用 setTimeout 包装了函数,它将永远运行。如果您在屏幕截图上注意到,js 异常发生了这么多次。这也是我们真实应用程序上正在发生的事情。我不知道为什么。

这里是小提琴:http://jsfiddle.net/ux12xoya/1/

    // JSON Request
    var auxTime = new Date();
    var jQueryCallbackRandom = auxTime.getTime();

    var callParameters = {
        url: 'http://jsfiddle.net/echo/jsonp/',
        timeout: 2,
        dataType: "jsonp",
        data: { echo: "Hello World!" },
        jsonpCallback: "jQueryRandom_" + jQueryCallbackRandom,
        success: function(){
         console.log("success");   
        },
        error: function(jqXHR, textStatus){
            console.log("failed with error: " + textStatus);
            window["jQueryRandom_" + jQueryCallbackRandom] = function() {
              window["jQueryRandom_" + jQueryCallbackRandom] = null;
            };
        }       
    };

    var timeout = setTimeout(callAjax, 5000)

    function callAjax() {
        $.ajax(callParameters);
        clearTimeout(timeout);
        timeout = setTimeout(callAjax, 5000)
    }

这里是错误截图:http://i.imgur.com/IFiW9ij.png

【问题讨论】:

  • 你必须把所有变量都放在callAjax ... 以使它们成为callAjax 范围的本地变量
  • 您对每个请求都使用相同的jQueryCallbackRandom。如果任何一个请求花费的时间超过 5 秒,您就会开始遇到冲突。停止手动命名回调,这将停止发生。
  • 不,不是,您在顶部设置一次,然后为每个请求重用它。
  • callParameters 只初始化一次,因此在每次 $.ajax() 调用时它们将完全相同。如果你移动所有这些东西(除了@Haketo 建议的callAjax() 函数内对setTimeout() 的启动调用,那么它就不会出现这些故障。(它仍然会有超时错误,因为你已经设置了一个非常短的超时限制。)

标签: javascript jquery jsonp typeerror


【解决方案1】:

这失败了,因为您的超时时间太短了。当请求超时时,回调从窗口中移除,然后当请求实际完成时,由于回调不在窗口上,所以抛出异常。它不会每次都发生,因为您对每个请求都使用相同的回调名称,有时它恰好在另一个请求尚未超时时完成,导致“成功”实际上并不成功.


您的代码实际上非常接近,问题的根源在于您没有为每个请求提供唯一的 JSONPCallback。您只需将这些变量移动到 ajax 函数中,以便为每个请求重新创建它们,从而使每个请求都有自己的基于 auxTime 的回调名称。

// JSON Request
var timeout = setTimeout(callAjax, 5000)

function callAjax() {
    var auxTime = new Date();
    var jQueryCallbackRandom = auxTime.getTime();

    var callParameters = {
        url: 'http://jsfiddle.net/echo/jsonp/',
        timeout: 5,
        dataType: "jsonp",
        data: { echo: "Hello World!" },
        jsonpCallback: "jQueryRandom_" + jQueryCallbackRandom,
        success: function(){
         console.log("success");   
        },
        error: function(jqXHR, textStatus){
            console.log("failed with error: " + textStatus);
            window["jQueryRandom_" + jQueryCallbackRandom] = function() {
              window["jQueryRandom_" + jQueryCallbackRandom] = null;
            };
        }       
    };
    $.ajax(callParameters);
    clearTimeout(timeout);
}

http://jsfiddle.net/ux12xoya/2/

【讨论】:

  • 这个 poc 的目标是捕获 Uncaught TypeError。在我们的产品中,我们的超时时间是 60 秒,但它仍然很少发生
  • 发生超时总是会报错,因为这是JSONP。这是不可避免的。如果回调不再可用,则会发生类型错误。
  • 这根本不是错误,它只是它的工作方式。 JSONP 本身就是 hacky,它不是浏览器支持的官方协议,相反,它是一个聪明的解决方法,通过使用
  • 我必须实际查看代码。如果它与问题中的相同,那么它肯定有可能不是唯一的。
  • 如果我要添加一个自动重试功能,我会这样做,它可以根据请求打开和关闭。然后你可以过滤它而不影响jsonp请求,问题就解决了。
猜你喜欢
  • 1970-01-01
  • 2021-12-15
  • 2011-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多