当前位置:网站首页>How to send a reliable request before closing the page

How to send a reliable request before closing the page

2022-07-04 22:38:00 swlws9527




One 、 problem

from A Page goes to B Before page , Send a message to the background /log request , How to ensure that this request will be received and processed .

Scene: the repetition

function nextPage() {
    
  fetch("/log", {
    
    method: "POST",
    headers: {
    
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
    
      some: "data",
    }),
  });

  window.location.href = "/other.html";
}

In this code , After successful page switching , The background cannot receive /log Requested . reason :

  1. js The implementation of can be divided into The main thread Asynchronous thread
  2. When the page enters terminated In the state of , Will release all resources . in other words , here Asynchronous thread Context not executed in , Will no longer be dealt with .

Two 、 Solution

2.1 async/await

Since the request is executed because of asynchrony , Then change to synchronization .

async function nextPage() {
    
  await fetch("/log", {
    
    method: "POST",
    headers: {
    
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
    
      some: "data",
    }),
  });

  window.location.href = "/other.html";
}

This method will block code execution

2.2 keepAlive

fetch Set in keepalive by true when , Even if the page that initiated the request is terminated state , Will also remain connected . Use this feature , You can send reliable requests .

function nextPage() {
    
  fetch("/log", {
    
    method: "POST",
    headers: {
    
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
    
      some: "data",
    }),
    keepalive: true,
  });

  window.location.href = "/other.html";
}

2.3 navigator.sendBeacon

Use sendBeacon() The method allows users to send data asynchronously to the proxy server , At the same time, it will not delay the unloading of the page or affect the loading performance of the next navigation , It means :

  • Data transmission is reliable .
  • Data asynchronous transmission .
  • It does not affect the loading of the next navigation .

Code example :

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

  window.location.href = "/other.html";
}

sendBeacon()API Adding request headers is not supported , You can use Blob Make some changes to support the request header

function nextPage() {
    
  const blob = new Blob([JSON.stringify({
     some: "data" })], {
    
    type: "application/json; charset=UTF-8",
  });
  navigator.sendBeacon("/log", blob);

  window.location.href = "/other.html";
}

It should be noted that , stay Chrome Of network Under the panel , Its document type is ping, It's not common fetch、xhr type .

2.4 <a> Labeled ping attribute

More and more manufacturers support ping The attribute is . Example :

<a href="/other.html" ping="/log">other page</a>

Click on a When labeling , An additional request will be sent /log, Its request header contains several special values :

{
    
  "ping-from": "http://127.0.0.1:3000/",
  "ping-to": "http://127.0.0.1:3000/other.html",
  "content-type": "text/ping"
}

3、 ... and 、 Options

If , have access to fetch()+keepalive:

  • You need to customize the request header .
  • Use GET request , No POST request .
  • Support older browsers ( Such as IE), And it has been loaded fetch polyfill.

But if the following conditions are met ,sendBeacon() Maybe a better choice :

  • Make a simple service request , Don't need too much customization .
  • Prefer cleaner 、 More elegant API.
  • We want to ensure that your request does not compete with other high priority requests sent in the application .

Reference resources :

原网站

版权声明
本文为[swlws9527]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/185/202207042212372297.html