同步XHR (AJAX)已弃用


Synchronous XHR (AJAX) Deprecated?

我已经在我的网站上建立了一个翻译系统(由您真正开发),这基本上是一些php文件返回数组。

hello.php

return [
  'world' => 'Hello, world!'
];

通过类轻松访问

Lang::get('hello', 'world'); // Hello, world!

在构造响应时,这一切都很好,但是在某些情况下,我需要在没有请求的情况下显示翻译。例如,我做了另一个方便的功能,我在表单上有PHP验证,我已经自动生成JavaScript规则,在发送请求之前在页面上执行相同的验证,如果验证失败,那么我需要显示适当的消息-可能有数百种可能的验证失败的原因。请注意,这只是一个示例用例,因此我看到的解决方案是:

  • 我可以用初始请求加载所有翻译字符串,并准备显示其中的任何一个。这将浪费大量的带宽,因为大多数时候,大多数字符串根本不需要。我可以更进一步,将它们缓存在本地存储中,但是缓存整个站点的文本内容(可翻译的)可能超过了允许的存储量,因此这似乎不太可靠。

  • 我可以发送一个请求,无论如何检索我需要的翻译,这在示例用例中破坏了拥有这样的验证的整个点,但这是一个比前一个更好的解决方案,此外,如果做得对,我可以从浏览器的内部缓存中受益,它只会请求翻译一次,并在随后的请求中从缓存中加载它们,这听起来不错。

我选择了第二个解决方案,我面临的问题是:

我有一个JavaScript函数,我将用伪代码来描述。

function translate(file, key) {
  if(!storage[file]) {
    storage[file] = sendAjaxAndLoadFileFromServer();
  }
  return storage[file][key];
}
var storage = {};

我不知道如果浏览器缓存了请求,页面上的二级缓存是否需要,但它似乎不会造成伤害?我也想听听你的意见。

现在可以工作了,因为我正在同步发送AJAX请求。然而,我在控制台中看到这条消息:

主线程上的同步XMLHttpRequest是不赞成的,因为它对最终用户的体验有不利影响。获取更多帮助http://xhr.spec.whatwg.org/

在建议的网站上,我没有看到任何暗示我不应该使用同步请求的东西,但是这个消息中的deprecated这个词让我思考。

不幸的是,这是我可以实现这个解决方案的唯一方法(通过同步请求),因为这个函数是在需要返回值的地方调用的,比如

new Dialog(translate('world'));

我不知道如何在这样的上下文中实现承诺或任何东西。

所以问题是:

我可以使用同步AJAX请求吗?它们会在不久的将来消亡吗?

恕我直言,没什么好担心的。因为它影响UI(冻结),所以不推荐使用它,但它是AJAX的一个特性。但也许你可以做异步方式-显示等待覆盖,收集所有未翻译的消息,然后隐藏覆盖,然后显示你需要的消息。

根据评论,也许有办法:

也许你可以使翻译返回立即,但与回调。每次调用翻译队列字符串来翻译并显示"等待"。在回调中你会得到翻译后的字符串

将会有另一个进程- translator。如果queue不为空,它将定期转换排队的字符串(例如每10毫秒),并为每个字符串调用注册回调。处理完毕后,如果队列为空,则隐藏"等待"。

效果将是-第一个翻译请求显示"等待",最后一个服务请求隐藏它。所有的翻译都是分开的,但分批提供。您所需要做的就是将字符串替换逻辑移到回调函数中。

这将是一个分两部分的回答,因为你的问题开启了两个不同的话题。

同步AJAX

不推荐使用是有原因的。如果你做一个同步ajax请求,整个网站在请求期间冻结。当互联网连接很快,服务器响应迅速,这将只需要几毫秒。但是如果浏览器需要等待更长的响应时间,网站可能会冻结几秒钟,这可能会让你的用户感到沮丧。这就是为什么应该避免同步ajax请求。

错误消息的翻译

这里还有一些你可能想要考虑的选项:

  • 按语言分段翻译文件。始终只加载活动语言的文本。如果你支持语言,这只加载1/5的文本。
  • 按表单或页面或其他相关翻译消息分组对翻译文件进行分段。然后在显示表单之前加载特定于该表单的翻译。这将进一步减少不必要消息的加载。

请求持续时间= ping +响应大小/连接速度

(用于静态文件)Ping是向服务器发送请求并返回第一个字节所花费的时间。在光纤上需要1毫秒,在移动设备上需要数百毫秒。在100ms ping和100kB/s带宽的3G连接中,以下两个都需要200ms:

  • 加载10kB的数据(ping 100ms +传输100ms = 200ms)
  • 发送两个请求,每个请求几乎不传输数据(ping 100ms + ping 100ms = 200ms)

因此,选择一次为多个消息加载翻译的解决方案可能是完全可以接受的,因为您可以避免由于服务器和客户端之间的ping而浪费时间。