使用react-native開發app時,通常使用fetch函數與後臺進行交互。請求後臺接口時,爲了防止用戶等待太長時間需要設置timeout,但是原生的fetch並沒有設置timeout的地方。本文介紹一種設置timeout的方法。
一、修改fetch源代碼
self.fetch = function(input, init) {
return new Promise(function(resolve, reject) {
var request = new Request(input, init)
var xhr = new XMLHttpRequest()
xhr.onload = function() {
var options = {
status: xhr.status,
statusText: xhr.statusText,
headers: parseHeaders(xhr.getAllResponseHeaders() || '')
}
options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')
var body = 'response' in xhr ? xhr.response : xhr.responseText
resolve(new Response(body, options))
}
xhr.onerror = function() {
reject(new TypeError('Network request failed'))
}
xhr.ontimeout = function() {
reject(new TypeError('Network request failed'))
}
xhr.open(request.method, request.url, true)
if (request.credentials === 'include') {
xhr.withCredentials = true
}
if ('responseType' in xhr && support.blob) {
xhr.responseType = 'blob'
}
request.headers.forEach(function(value, name) {
xhr.setRequestHeader(name, value)
})
//設置fetch函數請求的超時時間
if(init!=null&&init.timeout!=null){
xhr.timeout=init.timeout;
}
xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
})
}
觀察代碼能夠發現,fetch函數將input與init兩個參數封裝成一個Request類並通過XMLHttpReauest類的send方法發送請求。其中input爲接口的url地址,init爲fetch函數的設置對象,包括method、headers等屬性。
RCTNetworking.sendRequest(
this._method,
this._trackingName,
this._url,
this._headers,
data,
nativeResponseType,
incrementalEvents,
this.timeout,
this.__didCreateRequest.bind(this),
this.withCredentials
);
繼續觀察XMLHttpReauest的代碼發現,XMLHttpReauest進一步通過原生類RCTNetworking的sendRequest方法發送請求,其中this.timeout中this爲XMLHttpReauest的實例對象xhr。因此,可以通過爲xhr設置timeout達到爲fetch函數設置timeout的目的,只需要在fetch函數中添加以下代碼:
//設置fetch函數請求的超時時間
if(init!=null&&init.timeout!=null){
xhr.timeout=init.timeout;
}
現在,你可以在fetch函數中設置設置timeout值了。
return fetch(constant.SERVICE_URL + srvName, {
method: 'POST',
credentials: 'include', //credentials默認omit,即不傳cookie
mode: 'cors',
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: args,
timeout: constant.TIMEOUT
})