关于在react-native中使用fetch请求遇到的坑
程序员文章站
2022-04-15 18:37:51
...
在rn官网中,网络请求只提供了fetch。首先来了解一下什么是fetch?在原来的HTTP请求中是用 XMLHttpResquset
,现在fetch是一个很好的替代方法,可以很容易的被其他技术使用。其次呢,fetch还利用了异步的特性——他是基于Promise
的。
前面第一到三部分是我给fetch做的笔记,已经知道fetch用法的看客可以直接绕过,从第四部分看起。
一、fetch与ajax的区别
- 当接收到一个代表错误的 HTTP 状态码时,从 fetch()返回的 Promise 不会被标记为 reject, 即使该 HTTP 响应的状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (但是会将 resolve 的返回值的 ok 属性设置为 false ),仅当网络故障时或请求被阻止时,才会标记为 reject。
- 默认情况下,fetch 不会从服务端发送或接收任何 cookies, 如果站点依赖于用户 session,则会导致未经认证的请求(要发送 cookies,必须设置 credentials 选项)。
二、fetch的请求
fetch在英文中的原意就是获取
的意思,所以一个fetch请求比XMLHttpResquset
写起来简单多了。
fetch(url,options)
.then(response => response.json())
.then(data => {
console.log(data); // 这里是请求成功 包括 404 或 500时
}).catch( error => {
console.log(error); // 这里是网络故障的时候
})
-
url
即请求的URL地址 -
options
一个可以控制不同配置的 init 对象:(具体如下)
-
method
: 请求使用的方法,如 GET、POST。 -
headers
: 请求的头信息,形式为 Headers 的对象或包含 ByteString 值的对象字面量。 -
body
: 请求的 body 信息:可能是一个 Blob、BufferSource、FormData、 URLSearchParams 或者 USVString 对象。注意 GET 或 HEAD 方法的请求不能包含 body 信息。 -
mode
: 请求的模式,如 cors、 no-cors 或者 same-origin。 -
credentials
: 请求的 credentials,如 omit、same-origin 或者 include。为了在当前域名内自动发送 cookie , 必须提供这个选项, 从 Chrome 50 开始, 这个属性也可以接受 FederatedCredential 实例或是一个 PasswordCredential 实例。 -
cache
: 请求的 cache 模式: default 、 no-store 、 reload 、 no-cache 、 force-cache 或者 only-if-cached 。 -
redirect
: 可用的 redirect 模式: follow (自动重定向), error (如果产生重定向将自动终止并且抛出一个错误), 或者 manual (手动处理重定向). 在Chrome中,Chrome 47之前的默认值是 follow,从 Chrome 47开始是 manual。 -
referrer
: 一个 USVString 可以是 no-referrer、client或一个 URL。默认是 client。 -
referrerPolicy
: Specifies the value of the referer HTTP header. May be one of no-referrer、 no-referrer-when-downgrade、 origin、 origin-when-cross-origin、 unsafe-url 。 -
integrity
: 包括请求的 subresource integrity 值 ( 例如: sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=)。
三、get请求
get请求很简单,就是在url后面拼上请求参数,为节省时间,这里就不阐述了。
四、post请求
post请求在有点坑的地方,就在参数的传递。
关于请求参数,网上找到了两种方法,但是都返回请求错误。
注:我rn接口和pc的接口一致,换汤不换药的那种。
let params = {
name: '张三',
age: 18
}
方法一:
param = JSON.stringify(params);
方法二:
//将"key1=value1&key2=valu2" 形式封装整FromData形式
let formData = new FormData();
formData.append("name","张三");
formData.append("age",18);
但是这种方式后端那边还是解析不了。于是就来了方法三。
方法三:
strDicToString(data){
let result='';
let arr=[];
for (let [k, v] of Object.entries(data)) {
let str=k+'='+v;
arr.push(str)
}
for (var i=0;i<arr.length;i++){
if (i===arr.length-1){
result+=arr[i]
}else {
result+=arr[i]+'&'
}
}
return result
}
使用:
param = strDicToString(params);
/**
* 获取网络数据
* @param url 地址
* @param param 上传参数
* @param method 请求方式
* @returns {Promise<any> | Promise}
*/
fetchPostData(url,param,method='POST'){
return new Promise((resolve,reject) => {
let fetchOptions = {
method,
body:this.strDicToString(param),
headers:{
'Accept':'application/json',
'Content-Type':'application/x-www-form-urlencoded'
},
};
fetch(URL,fetchOptions)
.then(response => {
return response.json();
}).then(responseData => {
resolve(responseData);
}).catch(error => {
reject(error);
})
})
}
五、请求超时设置
网上提供的解决方案是利用 Promise.race()
。
Promise.race([fetch(URL,fetchOptions),Promise((res,rej) => {
setTimeout( () => rej('请求超时'),3000);
})])
.then(response => {
return response.json();
}).then(responseData => {
resolve(responseData);
}).catch(error => {
reject(error);
});
这里放第三个Promise
返回reject时,整个Promise.race()
就返回reject。这个表面是解决了请求超时的问题,但是并没有真正阻断HTTP请求。
如在表单提交的场景中,超过规定时间(如3s)以后,给用户展示的请求超时(这个时候请求实际上没有停止)。但是第4s的时候,可能提交成功了。最后可能会导致用户重复操作。
最后各种折腾无果,于是就果断放弃了fetch,改用axios插件。
六、总结
- fetch可以用在简单的请求数据中,比原来的
XMLHttpResquset
方便许多,还可以异步调用。 - 在复杂的请求中,fetch是不能中断请求过程的。这里只能改用其他的请求方式,如axios。
上一篇: 客户端发送请求的方式以及服务端接收请求
下一篇: fetch API的实际用法对比
推荐阅读