使用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
})