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