First of all, this article is not intended to explain the exact use of FETCH. If not, please refer to the MDN Fetch tutorial.

Fetch does not carry cookies by default

Configure the credentials entry, which has three values:

  • Omit: default value, omit the delivery of cookies
  • Same-origin: Cookies can be sent only in the same domain but not across domains
  • Include: Cookies can be sent either in the same domain or across domains

Credentials express the same meaning as the withCredentials attribute in XHR2, indicating whether the request carries cookies

Thus, to fetch requests with cookie information, you only need to set the credentials option, for example, FETCH (URL, {credentials: ‘include’});

The FETCH request does not reject certain incorrect HTTP states

This is mainly caused by the fact that fetch returns a promise, because fetch does not reject promises in some incorrect HTTP states such as 400, 500, etc. Instead, it will be resolved. A fetch is rejected only if a network error causes the request to be rejected; So the fetch request is generally wrapped in a layer, as shown in the following code:

function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return response;
  }
  const error = new Error(response.statusText);
  error.response = response;
  throw error;
}
function parseJSON(response) {
  return response.json();
}
export default function request(url, options) {
  let opt = options||{};
  return fetch(url, {credentials: 'include'. opt}) .then(checkStatus) .then(parseJSON) .then((data) = > ( data ))
    .catch((err) = > ( err ));
}
Copy the code

Fetch does not support timeout processing

Method 1: Simple setTimeout mode

var oldFetchfn = fetch; // Intercept the original fetch method
window.fetch = function(input, opts){// Define a new fetch method that encapsulates the old fetch method
    return new Promise(function(resolve, reject){
        var timeoutId = setTimeout(function(){
            reject(new Error("fetch timeout"))
        }, opts.timeout);
        oldFetchfn(input, opts).then(
            res= >{
                clearTimeout(timeoutId);
                resolve(res)
            },
            err=>{
                clearTimeout(timeoutId);
                reject(err)
            }
        )
    })
}
Copy the code

Of course, xHR-like abort can be simulated from above:

var oldFetchfn = fetch; 
window.fetch = function(input, opts){
    return new Promise(function(resolve, reject){
        var abort_promise = function(){
            reject(new Error("fetch abort"))};var p = oldFetchfn(input, opts).then(resolve, reject);
        p.abort = abort_promise;
        returnp; })}Copy the code

The Promise. Race method accepts a Promise instance array parameter, indicating that any of the multiple Promise instances changes state first, then the state of the Promise instance returned by the RACE method will change accordingly. For details, see here.

var oldFetchfn = fetch; // Intercept the original fetch method
window.fetch = function(input, opts){// Define a new fetch method that encapsulates the old fetch method
    var fetchPromise = oldFetchfn(input, opts);
    var timeoutPromise = new Promise(function(resolve, reject){
        setTimeout((a)= >{
             reject(new Error("fetch timeout"))
        }, opts.timeout)
    });
    retrun Promise.race([fetchPromise, timeoutPromise])
}
Copy the code

Fetch does not support JSONP

npm install fetch-jsonp --save-dev
Copy the code

Then use it as follows:

fetchJsonp('/users.jsonp', {
    timeout: 3000.jsonpCallback: 'custom_callback'
  })
  .then(function(response) {
    return response.json()
  }).catch(function(ex) {
    console.log('parsing failed', ex)
  })
Copy the code

Fetch does not support progress events

XHR natively supports progress events, such as the following code:

var xhr = new XMLHttpRequest()
xhr.open('POST'.'/uploads')
xhr.onload = function() {}
xhr.onerror = function() {}
function updateProgress (event) {
  if (event.lengthComputable) {
    var percent = Math.round((event.loaded / event.total) * 100)
    console.log(percent)
  }
xhr.upload.onprogress =updateProgress; // Upload progress event
xhr.onprogress = updateProgress; // Download the progress event
}
xhr.send();
Copy the code

Fetch, however, does not support progress events; The good news is that fetch’s internal design implements Request and Response classes according to its guiding specification standards; Response encapsulates some methods and properties that can be accessed through Response instances, such as Response.json (), response.body, etc.

Response.body is a readable byte stream object that implements a getRender() method.

The getRender() method is used to read the original byte stream of the response, which can be read in a loop until the body content has been transferred.

Therefore, the progress of FETCH can be simulated by using this point

// fetch() returns a promise that resolves once headers have been received
fetch(url).then(response= > {
  // response.body is a readable stream.
  // Calling getReader() gives us exclusive access to the stream's content
  var reader = response.body.getReader();
  var bytesReceived = 0;

  // read() returns a promise that resolves when a value has been received
  reader.read().then(function processResult(result) {
    // Result objects contain two properties:
    // done - true if the stream has already given you all its data.
    // value - some data. Always undefined when done is true.
    if (result.done) {
      console.log("Fetch complete");
      return;
    }

    // result.value for fetch streams is a Uint8Array
    bytesReceived += result.value.length;
    console.log('Received', bytesReceived, 'bytes of data so far');

    // Read some more, and call this function again
    return reader.read().then(processResult);
  });
});
Copy the code

Fetch cross-domain problem

The fetch mode configuration item has three values, as follows:

  • Same-origin: This mode is not allowed to cross domains. It must comply with the same origin policy. Otherwise, the browser will return an error telling you that it cannot cross domains. The corresponding response type is basic.

  • Cors: This pattern supports cross-domain requests, which, as the name implies, cross domains in the form of CORS; Of course, this mode can also be same-domain requests without the need for additional BACKEND CORS support; The corresponding response type is CORS.

  • No-cors: This mode is used for cross-domain requests but the server does not have a CORS response header, that is, the server does not support CORS. This is also the special cross-domain request approach of FETCH; The response type is Opaque.

reference

  • MDN-ReadableStream
  • MDN fetch
  • Segmentfault.com/a/119000000…

link

  • Front-end knowledge system
  • React server renders the blog