"right"同步HTTP请求的方式

The "right" way to do synchronous HTTP request

你可能是来骂我的,但这是一个真实的用例。

在线教育的世界里,有SCORM课程。我必须让旧的 SCORM 课程在网站上运行。 SCORM 课程在浏览器中是 "web based" 和 运行,但他们希望在 iframe 中 运行 并且他们希望家长提供 GetValue 方法和 SetValue。

所以这些 SCORM 课程正在做 parent.SetValue("score", "90") 之类的事情并继续前进。如果有任何问题,该功能应该 return "false"。

SCORM 来自 90 年代,在现代网络中我们知道我们必须做 callbacks/promises 而 http 失败 "often"。您可能认为解决方案是一个 SetValue 写入本地数据,然后尝试并重试直到它通过,但 SCORM 课程通常设置为仅在 SetValue 有效时才移动到下一个屏幕,因此您不应该让用户前进,除非 SetValue 实际上保存在服务器上。

TL;DR

假设同步请求是一项要求,那么正确的方法是什么?

到目前为止我知道 $.ajax({async:false ... 但现在浏览器对此发出警告并且听起来他们将忽略您的同步请求。我在想也许使用 websockets 或 web worker 或其他东西是在现代编程中进行同步请求的正确方法。但我不知道如何提出这样的要求。而且SCORM课程的代码不允许更改(它们是用各种课程制作工具生成的)

澄清一下,我可以完全控制 SetValue 函数的实现。

$.ajax({async:false ... 会长期有效吗? (5-10 岁)

注意:在此用例中,完全冻结 UI 直到请求成功或失败是完全可以接受的。这就是课程的假设。

So far I know of $.ajax({async:false… but now browsers warn about that

这是正确的方法(如果您使用的是 jQuery),它会发送一个同步的 XMLHttpRequest。只是忽略警告。这是一个警告,表明您正在使用您已经知道的过时技术。

and sound like they're going to just ignore your request to be synchronous.

这不太可能。

I am thinking maybe using websockets or web workers or something is the right way to do a syncronous request in modern programming.

不,websockets 和 web worker 总是异步的,你不能用它们让你的异步请求看起来是同步的(事实上没有什么可以让你这样做)。

Will $.ajax({async:false… work long term? (5-10 years)

我们无法知道(而且 SO 不是 crystal 球)。可能会,尤其是在旧版浏览器中,也可能不会。浏览器供应商不愿意破坏 运行 网络功能的兼容性,并且不时仍然需要同步请求。在某些时候,太少(重要的)网页会使用它(<1%,<1‰,无论他们决定的阈值是多少),浏览器最终将有信心将其删除。到那时,您的企业就会意识到要弃用这些过时的课程制作工具。

根据我学习管理系统的经验,答案是:假装。

您写道:

it is entirely acceptable in this use case to completely freeze the UI until the request either succeeds or fails. That's what the courses assume.

也许您的课程假定了这一点,但在我过去十年中使用的任何学习管理系统中都不是这种情况。

据我所知,学习管理系统不使用同步请求,因为它们会阻止其他脚本,这给人的印象是 page/course 被锁定或损坏。解决方法是通过抽象层(包括 SCORM API)和 return 'true' 对课程使用异步调用,即使您无法验证 AJAX 调用实际上是成功的。

LMS 通常如何处理 SCORM 数据的高级视图:

课程启动时,LMS 从数据库中获取课程的所有现有 SCORM 数据,然后将其放入客户端的 JavaScript 对象中(可通过 SCORM API ).当您通过 SCORM 获取数据时,您通常是在获取这个预加载的 JS 对象中的数据——您不会直接从数据库获得实时响应。因此在使用 SCORM 的 API.GetValue.

时不需要 AJAX

当您尝试 API.SetValue 时,您最初将 key/value 对存储在 JS 对象中,而不是 SCORM 数据库中。因此,客户端JS对象需要同步指示是否成功存储数据('true')或不成功('false')。在您尝试使用 API.Commit().

将数据 持久化 到数据库之前,数据库 - 和 AJAX - 不会发挥作用

当您尝试从调用 AJAX 的 API.Commit() 获取成功值时,大多数 LMS 会伪造它。他们将执行异步请求以确保课程不会被破坏,因此从 Commit() 编辑的值 return 几乎总是 'true'。不靠谱。