Javascript专门用于发送单向请求的几种可靠方式 - css-tricks

22-03-28 banq

有两种推荐方式:
  1. 使用 Fetch 的keepalive标志
  2. Navigator.sendBeacon()函数专门用于发送单向请求

 

使用 Fetch 的keepalive标志
如果在使用时将该keepalive标志设置为,则相应的请求将保持打开状态,即使发起该请求的页面已终止。
案例:

<a href="/some-other-page" id="link">Go to Page</a>

<script>
  document.getElementById('link').addEventListener('click', (e) => {
    fetch("/log", {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      }, 
      body: JSON.stringify({
        some: "data"
      }), 
     [b] keepalive: true[/b]
    });
  });
</script>

 

使用Navigator.sendBeacon()
Navigator.sendBeacon()函数专门用于发送单向请求(详细)。
一个基本的实现看起来像这样,发送一个POST带有字符串化的 JSON 和一个“text/plain” Content-Type:

navigator.sendBeacon('/log', JSON.stringify({
  some: "data"
}));


但是此 API 不允许您发送自定义标头。
因此,为了让我们以“application/json”的形式发送数据,我们需要做一些小调整并使用Blob:

<a href="/some-other-page" id="link">Go to Page</a>

<script>
  document.getElementById('link').addEventListener('click', (e) => {
    const blob = new Blob([JSON.stringify({ some: "data" })], { type: 'application/json; charset=UTF-8' });
    navigator.sendBeacon('/log', blob));
  });
</script>


相比fetch():这种方式以低优先级发送。
 

Ping属性
值得一提的是,越来越多的浏览器支持该ping属性。当附加到链接时,它会触发一个小POST请求:

<a href="http://localhost:3000/other" ping="http://localhost:3000/log">
  Go to Other Page
</a>

这些请求标头将包含单击链接的页面 ( ping-from),以及href该链接的值 ( ping-to):

headers: {
  'ping-from': 'http://localhost:3000/',
  'ping-to': 'http://localhost:3000/other'
  'content-type': 'text/ping'
  // ...other headers
},


它在技术上类似于发送beacon,但有一些明显的限制:
  1. 它严格限制在链接上的使用,如果您需要跟踪与其他交互相关的数据,例如按钮点击或表单提交,这将使其无法启动。
  2. 浏览器支持很好,但不是很好。在撰写本文时,Firefox 特别没有默认启用它。
  3. 您无法随请求一起发送任何自定义数据。如前所述,您将获得的最多的是几个 ping-*标题,以及其他任何标题。

考虑到所有因素,ping如果您可以发送简单的请求并且不想编写任何自定义 JavaScript,那么它是一个很好的工具。但是,如果您需要发送更多实质内容,则可能不是最好的选择。
 

那么,我应该接触哪一个?
使用fetchwithkeepalive或sendBeacon()发送你的最后一秒请求肯定有权衡。为了帮助辨别哪种方法最适合不同的情况,需要考虑以下几点:
选择fetch():_keepalive:

  • 您需要轻松地随请求传递自定义标头。
  • 您想向GET服务发出请求,而不是POST.
  • 您正在支持较旧的浏览器(如 IE)并且已经fetch加载了一个 polyfill。

但sendBeacon()在以下情况下可能是更好的选择:
  • 您正在发出不需要太多自定义的简单服务请求。
  • 您更喜欢更简洁、更优雅的 API。
  • 您希望确保您的请求不会与应用程序中发送的其他高优先级请求竞争。