在等待响应时确定AJAX请求是否已完成

时间:2013-05-24 16:40:14

标签: php javascript jquery ajax

我有一个AJAX表单,用户可以在其中上传CSV文件。这些文件相当小,服务器端处理将比实际文件上载花费更多时间。然而,上传可能仍需要一两秒钟,具体取决于文件大小和连接速度。此外,用户必须知道服务器端操作是成功还是失败。

现在我想区分“上传文件”和“等待回复”,这样我就可以向用户显示相应的消息/指示图标等。

我正在使用jQuery的$.ajax,我可以在其中指定complete() - 回调。但是,在收到服务器的响应之前,这不会触发。据我所知,没有requestComplete() - 回调。

那么,简而言之,有没有办法检测AJAX请求是否已完全发送到服务器,即使服务器没有响应呢?

如果可能的话,我宁愿不在服务器和客户端推送(WebSockets或Comet等)上使用异步处理。 (服务器运行PHP)。

3 个答案:

答案 0 :(得分:4)

请参阅Session Upload Progress功能。

启用后,PHP将在用户会话中存储上传进度信息。然后,您可以通过执行ajax pull来获取此数据。

或者,APC有一个similar feature

答案 1 :(得分:2)

arnaud576875的答案适用于实际的文件上传(您说可能需要或可能不需要几秒钟)。您可能需要这两种方法。一般来说,PHP中没有用于跟踪脚本内部进度的机制 - PHP也不知道它处于什么样的状态,也不一定要将任何数据返回给调用者直到结束(即使它确实如此,你的JS也不会收到部分输出)。

执行此操作的标准方法是让浏览器不断轮询服务器以获取脚本的进度。上传是独立的,所以你也需要找到它并合并这两个数字 - 这需要估计每个任务(上传,处理)需要多长时间以及一些好的代数技能。

在你的脚本中你需要确定完成的百分比(如果你有一个很大的foreach循环这很容易)并将它存储在某个地方(数据库,文件,APC)。您还需要一种识别用户的方法(user_id和/或从javascript传递随机数作为ID)。

您的轮询脚本(例如,每2秒)将通过传递唯一ID来获取脚本进度的此编号。

答案 2 :(得分:2)

根据your comment的要求,以下是my comment的更完整说明。

就跟踪上传进度而言,无需编写特定的服务器端代码即可支持跟踪上传进度。如你所说,我在谈论onprogress event provided by XMLHttpRequest level 2。它非常易于使用。看看我刚才提到的链接的一小部分:

var oReq = new XMLHttpRequest();

oReq.addEventListener("progress", updateProgress, false);

oReq.open();

oReq.send(something);

// progress on transfers from the server to the client (downloads)
function updateProgress (oEvent) {
  if (oEvent.lengthComputable) {
    var percentComplete = oEvent.loaded / oEvent.total;
    // ...
  } else {
    // Unable to compute progress information since the total size is unknown
  }
}

关于你问题中提到的其他项目:

  

我想区分“上传文件”和“等待回复”,因此我可以向用户显示相应的消息/指示图标等。

这在理论上肯定是可能的。我在我维护的跨浏览器上传库Fine Uploader中所做的是等到最后一个字节被发送(根据我的进度处理程序),然后在UI中的文件旁边添加一条消息,例如“处理......”。我已经假设,随着最后一个字节的发送,服务器正在对文件执行一些任务,我现在只是在等待响应。

我说这可以在理论上检测,但实际上并不是跨浏览器。为什么?我在a case in the Fine Uploader Github repository对此进行了评论。我将在此处包含我的全部评论:

  

我注意到Firefox没有触发它的最后一个进度事件   收到来自服务器的响应,这有点令人失望。   提交Firefox issue来跟踪此“问题”。

     

听起来好像Firefox可能正在关注   XHR V2规格,而Chrome则秉承规范的“精神”。   Chrome的实施,导致最后一次进展事件   在最后一个字节被“发送”之后被解雇是最令人期待的,但是   这可能只是违反了规范。不确定IE10到底做了什么   因为我还没有调查过。 FF开发人员已经打开了一个帖子   在w3.org上,要求澄清一下。

     

Chromium dev认为“预期”行为实际上是一个webkit   细节,而不是Chrome特有的。这表明Safari和   Chrome表现出相同的行为,我已经验证过了。听起来   就像推动调整规范以允许webkit的行为一样   是预期的行为(根据规范的字母)。

     

请注意,我没有使用“loadend”事件来确定何时   浏览器已完成发送最后一个字节。我只是比较一下   处理“进度”事件时,“加载”值与“总”值   通知。如果这两个值相等,我就是声明文件   “完全发送”。根据规范,我应该能够做到这一点   (我认为)因为“loadend”事件在最后一次之后被解雇了   “进步”事件。有关详情,请参阅有关ProgressEvent的规范   的信息。

总而言之,这适用于Chrome和Safari,但不适用于FireFox。我不记得这是否适用于IE10。我永远不会记得因为我不使用IE。在Firefox中,进度指示器一旦达到99%左右就会被卡住,直到收到响应为止。

请注意,只有当用户代理支持File API时,我才能说明所有这些进度跟踪。这留下了IE9和更老。对于非文件API浏览器,有几个选项:

  1. 建立某种涉及客户端和服务器理解的GET请求的约定。客户端会定期向服务器发送GET请求,服务器必须响应文件进度。 FYI Fine Uploader有a scheduled feature request来更多地研究这个问题,尽管我对这种方法并不是很疯狂。
  2. 另一种选择,似乎更好一点,但可能有点限制(因为它取决于应用服务器)是利用nginx中的UploadProgress模块​​(如果您不熟悉则发音为Engine-X)。我被告知Apache有一个类似的模块,但是我无法找到任何相关的文档(尽管我根本没有考虑过这个)。 Fine Uploader也有[此功能请求(https://github.com/Widen/fine-uploader/issues/506),我将在不久的将来调查。
  3. 希望这能回答你的问题。