是否有任何理由使用同步XMLHttpRequest?

Dar*_*don 85 javascript ajax

似乎大多数人都使用XMLHttpRequest执行异步请求,但显然有能力执行同步请求这表明可能有正当理由这样做.那么这个有效的理由是什么呢?

Sam*_*uri 29

同步XHR对于保存用户数据非常有用.如果您处理beforeunload事件,则可以在用户关闭页面时将数据上载到服务器.

如果使用async选项完成此操作,则页面可能会在请求完成之前关闭.同步执行此操作可确保请求以预期方式完成或失败.

  • 编辑:我意识到你只是从一个懒惰的HN用户那里倾销txt,但是在这里很好地表达了一点时间. (4认同)

D.C*_*.C. 25

我认为随着HTML 5标准的进步,它们可能会变得更受欢迎.如果Web应用程序可以访问Web工作者,我可以预见开发人员使用专门的Web工作者来制作同步请求,正如Jonathan所说,确保一个请求发生在另一个请求之前.对于一个线程的当前情况,它是一个不太理想的设计,因为它阻塞直到请求完成.

  • 我认为他的意思是"网络工作者" (16认同)
  • -1. 这不是一个很好的答案,关于线程的整个讨论只是混淆了这个问题。萨米下面的答案实际上要好得多。 (3认同)

vol*_*ron 13

更新:

以下暗示 - 但未能成功交付 - 随着更好的异步请求处理的出现,确实没有理由使用同步请求,除非打算故意阻止用户做任何事情直到请求完成 - 听起来是恶意的: )

虽然这可能听起来很糟糕,但有时在用户离开页面之前或执行操作之前发生请求(或一系列请求)很重要 - 阻止其他代码执行(例如,阻止后退按钮)可能可能减少设计不良系统的错误/维护; 那说,我从来没有在野外看过它,并强调应该避免它.

图书馆,如承诺,通过回调链接流程来假装同步性.这适合大多数开发需求,其中需要有序的,非阻塞事件,使浏览器能够保持对用户的响应(良好的用户体验).

Mozilla文档中所述,有些情况下您必须使用同步请求; 但是,还列出了一种使用信标(在IE/Safari中不可用)的解决方法.虽然这是实验性的,如果它达到标准接受,它可能会在同步请求棺材中钉一个钉子.


您希望在任何类似事务的处理中执行同步调用,或者在需要任何操作顺序的任何地方执行.

例如,假设您要自定义一个事件,以便在播放歌曲后将您注销.如果首先发生注销操作,则永远不会播放该歌曲.这需要同步请求.

另一个原因是使用WebService时,尤其是在服务器上执行数学运算时.

示例:服务器具有值为1的变量.

 Step (1) Perform Update: add 1 to variable
 Step (2) Perform Update: set variable to the power of 3
 End Value: variable equals 8
Run Code Online (Sandbox Code Playgroud)

如果首先发生步骤(2),则结束值为2,而不是8; 因此操作顺序很重要并且需要同步.


在一个普通的现实世界的例子中,很少有同步调用可能是合理的.也许在单击登录然后单击需要用户登录的站点部分时.

正如其他人所说,它会占用你的浏览器,所以尽量远离它.

但是,用户通常希望停止当前正在加载的事件,然后执行其他操作,而不是同步调用.在某种程度上,这是同步,因为第一个事件在第二个事件开始之前退出.为此,请在xml连接对象上使用abort()方法.

  • @Zack:这是一个很好的例子,但是你可以对异步调用做同样的事情,具体取决于调用它的事件. (3认同)
  • -1事务处理是一个很好的例子,你必须使用保证的东西失败或成功 - 只是因为命令是同步的,并不意味着第一个请求成功...你依赖于响应告诉你这样.在此示例中,您将在第一个请求的result-handler中执行第二个请求***在这种情况下,它们也可能是异步的. (3认同)
  • +1存在一个有效的情况,即异步服务器请求可能导致逻辑竞争条件......但是,解决方案不必是同步性的.除非您的请求是从Web Worker处理的,否则最好编写一个对请求进行编号的传输层,然后确保按请求ID的顺序处理操作. (2认同)
  • @Mathew:只有当您的类似事务的过程依赖于它之前的操作的结果时,这才是正确的。如果您有一个按钮可以在您的页面中创建一个新对象(从服务器检索);如果它是异步的,用户可能会多次单击并返回许多对象。同步调用会阻止这种情况发生,并且只允许在第一个对象完成后创建另一个新对象,无论它是否出错。请注意措辞,我是故意把它做成***交易式***而不是***交易***。 (2认同)

hob*_*ave 8

我会说,如果您考虑在请求完成时阻止用户的浏览器,那么请确保使用同步请求.

如果请求序列化是您的目标,那么可以使用异步请求来完成此操作,方法是让先前请求的onComplete回调触发下一行.


小智 6

我可以看到,当必须在页面中依赖第一个资源完全起作用的其他静态资源之前加载变量位置中的资源时,可以使用同步XHR请求.事实上,我正在我自己的一个小子项目中实现这样的XHR请求,而JavaScript资源根据一组特定参数驻留在服务器上的变量位置.后续的JavaScript资源依赖于那些可变资源,并且必须保证在加载其他依赖文件之前加载这些文件,从而使应用程序完整.

这个想法基础真的有点扩展了vol7ron的答案.基于事务的过程实际上是应该进行同步请求的唯一时间.在大多数其他情况下,异步调用是更好的选择,在调用之后,DOM会根据需要进行更新.在许多情况下,例如基于用户的系统,您可以将某些功能锁定到"未授权用户",直到它们本身已经登录.在异步调用之后,这些功能通过DOM更新过程解锁.

我最后要说的是,我同意大多数人对此事的要点:应尽可能避免同步XHR请求,因为它的工作方式是浏览器锁定同步调用.在实现同步请求时,它们应该以通常被锁定的方式完成,无论如何,在页面加载实际发生之前,在HEAD部分中.


Hen*_*han 5

在某些情况下,jQuery 在内部使用同步 AJAX。当插入包含脚本的 HTML 时,浏览器将不会执行它们。这些脚本需要手动执行。这些脚本可能会附加点击处理程序。假设用户在附加处理程序之前单击某个元素,并且页面将无法按预期运行。因此,为了防止竞争条件,将使用同步 AJAX 来获取这些脚本。由于同步 AJAX 有效地阻止了其他一切,因此可以确保脚本和事件以正确的顺序执行。


小智 5

存在许多现实世界的情况,其中阻止UI正是期望的行为.

获取具有多个字段的应用程序,并且必须通过对远程服务器的xmlhttp调用来验证某些字段,该远程服务器提供此字段的值和其他字段值作为输入.

在同步模式下,逻辑很简单,用户遇到的阻塞很短,没有问题.

在异步模式下,用户可以在验证初始字段时更改任何其他字段的值.这些更改将触发其他xmlhttp调用,其中包含尚未验证的初始字段中的值.如果初始验证失败会怎样?纯洁的混乱.如果同意模式被弃用和禁止,应用程序逻辑将成为一个需要处理的噩梦.基本上,必须重新编写应用程序来管理锁(例如,在验证过程中禁用其他项).代码复杂性大大增加.如果不这样做可能会导致逻辑失败并最终导致数据损坏.

基本上问题是:什么更重要,非阻止的UI体验或数据损坏的风险?答案应该由应用程序开发人员保留,而不是W3C.

  • 我认为您将阻止用户交互与阻止浏览器线程的想法混为一谈。有十亿种简单的方法可以防止用户在不需要阻塞浏览器线程的异步调用期间继续与任何给定实体(表单字段等)交互。当线程阻塞时,无论如何都不能进行_任何_逻辑处理,这只是一种糟糕的情况;它产生的问题/潜在问题远多于它解决的问题,而这些问题/潜在问题实际上是无法解决的。 (2认同)