杂记:关于 navigator.sendBeacon 接口

6,638 阅读2分钟

今天在 GoogleChrome 的 Samples 仓库中看到了 navigator.sendBeacon 接口案例 demo

if ('sendBeacon' in navigator) {
  window.addEventListener('pagehide', function() {
    navigator.sendBeacon(
      'https://putsreq.herokuapp.com/4GE2nVUuDoDGsNyKES2G',
      'Sent by a beacon!');
  }, false);
}

打开上面的页面,然后关闭,再点击进入地址 putsreq.herokuapp.com/4GE2nVUuDoD…,就能看见刚才你发送的请求信息。

在此之前,我已经知道的知识包括:

  1. navigator.sendBeacon 发送的是 POST 请求
  2. 传输数据有限制(在 Windows Chorme 浏览器下测试是 65536 个字符(出处))
  3. 底层是使用 Fetch API 实现的

第三点,我记不太清了,然后找出了之前翻译的文章确认一下。

回温到了这块内容:

Fetch API 支持一个 keepalive 选项,当设置为 true 时,保证不管发送请求的页面关闭与否,请求都会持续到结束。

window.addEventListener('unload', {
  fetch('/siteAnalytics', {
    method: 'POST',
    body: getStatistics(),
    keepalive: true
  });
}

Fetch API 语法如下:

navigator.sendBeacon(url, data);

由此,我想到 navigator.sendBeacon 底层的 Fetch API 实现可能是这样的:

function sendBeacon(url, data) {
  try {
    fetch(url, {
      method: 'POST',
      body: data,
      keepalive: true
    })
  } catch {
    return false
  }
  return true
}

我又找了当前 navigator.sendBeaconpolyfill 实现方式

下面列出是其核心代码:

function sendBeacon(url, data) {
  var event = this.event && this.event.type;
  var sync = event === 'unload' || event === 'beforeunload';
  var xhr = 'XMLHttpRequest' in this ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
  xhr.open('POST', url, !sync);
  xhr.withCredentials = true;
  xhr.setRequestHeader('Accept', '*/*');

  if (isString(data)) {
    xhr.setRequestHeader('Content-Type', 'text/plain;charset=UTF-8');
    xhr.responseType = 'text';
  } else if (isBlob(data) && data.type) {
    xhr.setRequestHeader('Content-Type', data.type);
  }

  try {
    xhr.send(data);
  } catch (error) {
    return false;
  }

  return true;
}

底层是借助了 XMLHttpRequest 实例的 open 方法第三个 sync 参数,该参数为 true 时,发送就是同步请求。这里只在页面的 unload 和 beforeunload 事件阶段才启用同步请求,否则都是异步请求。

扩展阅读:

(正文完)


广告时间(长期有效)

我有一位好朋友开了一间猫舍,在此帮她宣传一下。现在猫舍里养的都是布偶猫。如果你也是个爱猫人士并且有需要的话,不妨扫一扫她的【闲鱼】二维码。不买也不要紧,看看也行。

(完)