Ajax文件上传返回状态码0,准备状态为0(仅有时)。

5
我查看了以下线程:jQuery Ajax - Status Code 0?。然而,我没有找到一个明确的答案,而且我正在努力寻找问题的根源,因此我在这里发布帖子,希望有人能指点我正确的方向。
在我的代码中,我执行一个Angular HTTP post,它只发送基本的JSON数据,然后在成功回调函数中,我使用AJAX将文件上传到同一台服务器。(我知道我不应该同时使用jQuery和Angular,但我目前无法改变这一点)
它看起来像这样:
 var deferred = $q.defer()

 // first post
 $http.post(url,payload,{params: params, headers: headers)
   .then(function(response) {

    uploadFiles(response,deferred);
    // I am also sending google analytics events here

   }, function(error) {
      // do error stuff
   }

  return deferred.promise;

 // upload files function
 function uploadFiles(response,deferred){

 $ajax({
   type: 'POST',
   processData: false,
   contentType: false,
   data: data // this new FormData() with files appended to it,
   url: 'the-endpoint-for-the-upload',
   dataType: 'json',
   success: function(data) {
     // do success stuff here
    deferred.resolve(data);
   },
   error: function(jqXHR, textStatus, errorThrown) {

            var message = {};

            if (jqXHR.status === 0) {
              message.jqXHRStatusIsZero = "true";
            }

            if (jqXHR.readyState === 0) {
              message.jqXHRReadyStateIsZero = "true";
            }

            if (jqXHR.status === '') {
              message.jqXHRStatusIsEmptyString = "true";
            }

            if (jqXHR.status) {
              message.jqXHRStatus = jqXHR.status; 
            }

            if (jqXHR.readyState) {
              message.jqXHRReadyState = jqXHR.readyState;
            }

            if (jqXHR.responseText) {
              message.jqXHR = jqXHR.responseText; 
            }

            if (textStatus) {
              message.textStatus = textStatus;
            }

            if (errorThrown) {
              message.errorThrown = errorThrown;
            }

            message.error = 'HTTP file upload failed';

            logError(message);

            deferred.resolve(message);
      }
  }
})

}

这不是我原来的代码,但它们几乎完全相同。

问题在于它几乎总是可以工作,但是每隔几百个上传文件,可能会有三到四个失败。失败的意思是错误处理程序函数被调用,文件没有被上传。

当发生这种情况时,我得到 jqXHRStatus 0 和 jqXHRReadyState 0 的值。

唯一能够复制此问题的方法是在请求处理时点击浏览器上的刷新按钮,但用户已经确认他们没有这样做(虽然需要100%确认)

也许我的代码中存在严重的缺陷,我没有看到它?可能传递延迟变量不是一个好习惯?或者我没有考虑到取消ajax请求的另一种方式?同时发送谷歌分析事件会干扰吗?

如果您有任何建议,请告诉我,如果您需要更多信息,请告诉我。


1
如果在请求期间切换页面,或者页面没有完全加载就开始请求,可能会发生这种情况。如果数据不正确,也可能会发生这种情况。是否触发了某些事件导致请求中断?你确定这些都不是真的吗?因为我猜肯定有什么东西在处理请求时出了问题。 - Blackbam
你如何处理后端错误?可以展示一下后端代码吗? - alepeino
当您在浏览器上刷新时,如果要复制问题,则可以查看浏览器的开发工具控制台以获取更多信息。网络选项卡也可能有进一步的信息(XHR选项)。 - KorreyD
你能否创建一个 jsfiddle https://jsfiddle.net 来重现问题? - guest271314
你能在表单上看到你的HTML代码吗?请确认。 - Snoozer
2个回答

2
这意味着请求已被取消。可能有许多不同的原因,但请注意:这也可能是由于浏览器漏洞或问题造成的-因此我认为(个人意见)无法防止这种问题的发生。
举个例子,您收到503(服务不可用)响应。在这种情况下,您会怎么做?这也是一个偶发和不可预测的问题。只能接受并尝试重新发布数据。
不需要重复造轮子,我建议您实施: 使用延迟API重试ajax调用

0
我的猜测是你的代码在调用之前就已经执行了。也就是说,调用返回时没有返回任何内容,导致出现0错误。这是有道理的,因为错误是可变的。大多数情况下,它会正常返回,因为后端执行得足够快,但有时它不会,因为它花费了特别长的时间或发生了其他事情等。Javascript从来没有真正停止执行。它说它停止了,但特别是在angular和jquery之间传递多个ajax请求时,不奇怪如果它在实际完成您的angular post之前执行第二个ajax调用。这就是为什么刷新会复制错误,因为它会清除您的变量。
一些测试方法:
1. 在后端设置一个计时器,在返回任何内容之前等待几秒钟。这可能会使您的代码更加一致地失败。
2. 设置断点,查看javascript中何时被命中以及它们包含的值。
祝你好运!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接