首先聲明一下,本文不是要講解fetch的具體用法,不清楚的能夠參考 MDN fetch教程。前端
配置其 credentials 項,其有3個值:react
credentials所表達的含義,其實與XHR2中的withCredentials屬性相似,表示請求是否攜帶cookiegit
這樣,若要fetch請求攜帶cookie信息,只需設置一下credentials選項便可,例如fetch(url, {credentials: 'include'});github
這主要是由fetch返回promise致使的,由於fetch返回的promise在某些錯誤的http狀態下如400、500等不會reject,相反它會被resolve;只有網絡錯誤會致使請求不能完成時,fetch 纔會被 reject;因此通常會對fetch請求作一層封裝,例以下面代碼所示:npm
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 ));
}
複製代碼
方法一:單純setTimeout方式json
var oldFetchfn = fetch; //攔截原始的fetch方法
window.fetch = function(input, opts){//定義新的fetch方法,封裝原有的fetch方法
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)
}
)
})
}
複製代碼
固然在上面基礎上能夠模擬相似XHR的abort功能:segmentfault
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;
return p;
})
}
複製代碼
方法二:利用Promise.race方法 Promise.race方法接受一個promise實例數組參數,表示多個promise實例中任何一個最早改變狀態,那麼race方法返回的promise實例狀態就跟着改變,具體能夠參考這裏。後端
var oldFetchfn = fetch; //攔截原始的fetch方法
window.fetch = function(input, opts){//定義新的fetch方法,封裝原有的fetch方法
var fetchPromise = oldFetchfn(input, opts);
var timeoutPromise = new Promise(function(resolve, reject){
setTimeout(()=>{
reject(new Error("fetch timeout"))
}, opts.timeout)
});
retrun Promise.race([fetchPromise, timeoutPromise])
}
複製代碼
npm install fetch-jsonp --save-dev
複製代碼
而後在像下面同樣使用:跨域
fetchJsonp('/users.jsonp', {
timeout: 3000,
jsonpCallback: 'custom_callback'
})
.then(function(response) {
return response.json()
}).catch(function(ex) {
console.log('parsing failed', ex)
})
複製代碼
XHR是原生支持progress事件的,例以下面代碼這樣:數組
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; //上傳的progress事件
xhr.onprogress = updateProgress; //下載的progress事件
}
xhr.send();
複製代碼
可是fetch是不支持有關progress事件的;不過可喜的是,根據fetch的指導規範標準,其內部設計實現了Request和Response類;其中Response封裝一些方法和屬性,經過Response實例能夠訪問這些方法和屬性,例如response.json()、response.body等等;
值得關注的地方是,response.body是一個可讀字節流對象,其實現了一個getRender()方法,其具體做用是:
getRender()方法用於讀取響應的原始字節流,該字節流是能夠循環讀取的,直至body內容傳輸完成;
所以,利用到這點能夠模擬出fetch的progress
// 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);
});
});
複製代碼
fetch的mode配置項有3個值,以下:
same-origin:該模式是不容許跨域的,它須要遵照同源策略,不然瀏覽器會返回一個error告知不能跨域;其對應的response type爲basic。
cors: 該模式支持跨域請求,顧名思義它是以CORS的形式跨域;固然該模式也能夠同域請求不須要後端額外的CORS支持;其對應的response type爲cors。
no-cors: 該模式用於跨域請求可是服務器不帶CORS響應頭,也就是服務端不支持CORS;這也是fetch的特殊跨域請求方式;其對應的response type爲opaque。