欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于在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 对象:(具体如下)
  1. method: 请求使用的方法,如 GET、POST。
  2. headers: 请求的头信息,形式为 Headers 的对象或包含 ByteString 值的对象字面量。
  3. body: 请求的 body 信息:可能是一个 Blob、BufferSource、FormData、 URLSearchParams 或者 USVString 对象。注意 GET 或 HEAD 方法的请求不能包含 body 信息。
  4. mode: 请求的模式,如 cors、 no-cors 或者 same-origin。
  5. credentials: 请求的 credentials,如 omit、same-origin 或者 include。为了在当前域名内自动发送 cookie , 必须提供这个选项, 从 Chrome 50 开始, 这个属性也可以接受 FederatedCredential 实例或是一个 PasswordCredential 实例。
  6. cache: 请求的 cache 模式: default 、 no-store 、 reload 、 no-cache 、 force-cache 或者 only-if-cached 。
  7. redirect: 可用的 redirect 模式: follow (自动重定向), error (如果产生重定向将自动终止并且抛出一个错误), 或者 manual (手动处理重定向). 在Chrome中,Chrome 47之前的默认值是 follow,从 Chrome 47开始是 manual。
  8. referrer: 一个 USVString 可以是 no-referrer、client或一个 URL。默认是 client。
  9. 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 。
  10. 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