简体   繁体   中英

The request is missing when the page jumped

fetch(url, { method: 'POST', body: data, mode: 'cors' }).then(
    () => Promise.resolve(success),
    () => Promise.reject(error),
);

I have a page, the page has a jump button, when I click this button my page was jumped to another page, by location.href or window.open () .

But I would like to sending a request when the jump button is clicked, through the above fetch function.

Now, the problem is the page jumps too fast, the request is failed. When I set a long delay the jump is success, there is better way to handle it.

Forgive me,My English is not good, hope you can understand.

Method 1:

Although your XHR request may takes long time to execute, you can get readyState for that request to take advantage of it.

readyState number meanings:

  • 0: UNSENT open() has not been called yet.
  • 1: OPENED send() has been called.
  • 2: HEADERS_RECEIVED send() has been called, and headers and status are available.
  • 3: LOADING Downloading; responseText holds partial data.
  • 4: DONE The operation is complete.

Normally it's already fine to let go and move to next page with readyState >= 2 . Since most server start to process data at this point, and will not do any detection to stop even if you cancel request.

 var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://en.wikipedia.org/api/rest_v1/page/'); xhr.onreadystatechange = () => { console.log(xhr.readyState); if (xhr.readyState>=2) window.location.href = 'http://targeturl'; }; xhr.send(); 

Method 2:

This is another way that works via server delegation call.

var url = 'http://ip:port/uri?delegation=http%3A%2F%2Fwww.google.com';

fetch(url, { method: 'POST', body: data, mode: 'cors' }).then(
    () => {
       window.location.href = 'http://targeturl';
    },
    () => Promise.reject(error),
);

Then your server parse delegation part and do request ex: in another thread, and return ASAP, so the main page won't get blocks.

If you care more about the redirection than the request being successful, you can use Promise.race() to induce a timeout:

// Helper that creates a Promise that resolves after n milliseconds
const delay = n => new Promise(resolve => setTimeout(resolve, n));

Promise.race([fetch(url), delay(1000)])
  .then(() => redirectElsewhere())
  .catch(() => {/* handle error */});

Promise.race() takes an iterable of Promises, and resolves immediately when the first of them resolves (or rejects when the first rejects).

The effect this will give you is that you'll redirect when the request Promise resolves, or after 1000ms, whichever comes first.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM