【问题标题】:Why does the code inside xmlhttprequest work when async flag is set to false but not when it is set to true为什么 xmlhttprequest 中的代码在 async 标志设置为 false 时有效,但在设置为 true 时无效
【发布时间】:2016-05-10 06:12:40
【问题描述】:

我对 javascript 的使用相当陌生,希望能提供任何帮助。 我有一个应用程序,其中浏览器必须使用 xmlhttprequest 来接收来自服务器的响应(用于测试目的的 true/false),并且基于响应,客户端将打开一个文件选择对话框,供用户选择本地文件进行上传。

当我创建将异步标志设置为 FALSE 的 XMLHttpRequest 时,当客户端从服务器接收到“真”响应时,会打开一个文件选择对话框(适用于 Chrome、IE)。

当我创建 XMLHttpRequest 并将 async 标志设置为 TRUE(推荐)时,当客户端从服务器接收到“true”响应时,将遵循相同的代码路径,但是文件选择对话框永远不会打开并且没有错误显示在 Chrome 的调试器中,但它仍然在 IE 中工作。

代码如下:

... 
// user has clicked button to upload a file
$scope.uploadFile = function () { 
   request = new XMLHttpRequest();
   request.open("GET", "some-url", true);// false
   request.onreadystatechange = $scope.checkUploadPermissions;
   request.send();    
}

// the callback
// If the user has permission (based on various factors not shown here)
//   we open the dialog
// Otherwise we inform them that they are not allowed
$scope.checkUploadPermissions = function () {
  // simplified for brevity
  if (request.readyState == 4 && request.status == 200) {
    // for this sample, we are only checking if the server returned true/false
    var hasPerms = request.responseText;
    if (hasPerms === "true") {
       $scope.openFileSelector();
    }
    else {
       alert("You do not have permission to upload a file.");
    }
  }
}

// if the user has permission to proceed, we trigger a click on a hidden element
$scope.openFileSelector = function () {       
   angular.element("#presentUpload").trigger("click");
}
...

我想重申,当异步标志设置为 FALSE 时,此代码可以完美运行,但设置为 TRUE 时则无法正常运行。

将标志设置为 TRUE 时,我怎样才能使其正常工作。

提前谢谢你。

【问题讨论】:

  • 通常情况下,当某些东西同步而不是异步时,这是因为执行路径中的某些代码错误地假设同步执行,而一些应该在完成回调中执行的事情没有在那里完成。
  • angular.element("#presentUpload").trigger("click"); 应该做什么?您知道在异步执行 ajax 时是否会调用 openFileSelector() 吗?浏览器中的某些操作不允许异步执行,只有在处理实际用户事件的过程中才会起作用。
  • @jfriend00 如果用户有权上传文件,则对 openFileSelector() 的调用只是一个包含任何必要 TODO 的函数。对angular.element("#presentUpload").trigger("click"); 的调用只是调用html 页面上的一个隐藏按钮,该按钮打开并触发对<input type=file ... onchange=call_an_upload_callback .../> 的点击
  • 抱歉@jfriend00 被从我的办公桌上叫走,并且没有完成对上一条评论的正确编辑:对 openFileSelector() 的调用只是一个包含任何必要 TODO 的函数,如果用户有权限上传文件。对angular.element("#presentUpload").trigger("click"); 的调用只是调用html 页面上的一个隐藏元素,触发点击<input type=file ... onchange=call_an_upload_callback .../> 并打开文件上传对话框。在这两种情况下(异步设置为 TRUE 和 FALSE)所有代码行都会被命中,只是当它为 TRUE 时,对话框永远不会打开。
  • @codephreek jfriend00 的回答回答了这个问题。您不能在点击事件之外执行此操作。当您执行异步操作时,您就处于该事件之外。

标签: javascript jquery ajax asynchronous xmlhttprequest


【解决方案1】:

文件上传是浏览器中的一项功能,只能作为用户操作的直接结果启动(通常在您的 JS 代码处理鼠标单击或键盘事件时)。它不能由计时器或通过一些异步回调异步启动。

因此,当您将第一个 Ajax 调用设置为同步时,您的 JS 对隐藏元素的点击会出现在浏览器中,因为它仍在隐藏元素点击事件中,因此允许上传。当您的第一个 Ajax 调用设置为异步时,用户单击事件在您尝试单击隐藏元素时结束,并且浏览器不会弹出上传对话框。

详情请见Trigger click on input=file on asynchronous ajax done()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-10
    • 2019-08-11
    • 1970-01-01
    • 2015-02-19
    • 1970-01-01
    • 2020-04-19
    • 1970-01-01
    相关资源
    最近更新 更多