React Native Fetch封装那点事…

152次阅读

共计 4875 个字符,预计需要花费 13 分钟才能阅读完成。

每一门语言都离不开网络请求,有自己的一套 Networking Api。React Native 使用的是 Fetch。今天我们来谈谈与 Fetch 相关的一些事情。
purpose
通过这篇文章,你将了解到以下几点关于 Fetch 的独家报道

Fetch 的简单运用
Fetch 的主要 Api
Fetch 使用注意事项
Fetch 的 Promise 封装

fetch
fetch 的使用非常简单,只需传入请求的 url
fetch(‘https://facebook.github.io/react-native/movies.json’);
当然是否请求成功与数据的处理,我们还需处理成功与失败的回调
function getMoviesFromApiAsync() {
return fetch(‘https://facebook.github.io/react-native/movies.json’)
.then((response) => response.json())
.then((responseJson) => {
return responseJson.movies;
})
.catch((error) => {
console.error(error);
});
}
通过 response.json()将请求的返回数据转化成 json 数据以便使用。通过.then 来对数据进行转化处理或最终暴露给调用者;.catch 对异常的处理。
以上就是一个简单的网络请求,该请求默认是 get 方式。那么 post 又该如何请求呢?
Api & Note
在 fetch 中我们直接传入 url 进行请求,其实内部本质是使用了 Request 对象,只是将 url 出入到了 Request 对象中。
const myRequest = new Request(‘https://facebook.github.io/react-native/movies.json’);

const myURL = myRequest.url; // https://facebook.github.io/react-native/movies.jsonflowers.jpg
const myMethod = myRequest.method; // GET

fetch(myRequest)
.then(response => response.json())
.then(responseJson => {
//todo
});
如果我们需要请求 post,需要改变 Request 的 method 属性。
fetch(‘https://mywebsite.com/endpoint/’, {
method: ‘POST’,
headers: {
Accept: ‘application/json’,
‘Content-Type’: ‘application/json’,
},
body: JSON.stringify({
firstParam: ‘yourValue’,
secondParam: ‘yourOtherValue’,
}),
});
非常简单,在 url 后直接传入 {} 对象,其中指定 method 使用 post。
相信大家应该都知道 get 与 post 的一个主要区别是 get 可以在 url 上直接添加参数,而 post 为了安全都不采用直接将参数追加到 url 上,而是使用 body 来传给 service 端。
在使用 body 前,这里还需知道 headers。下面某个 post 请求的 headers 信息

需要注意的是 Content-Type 字段,它代表的是 service 端接收的数据类型,图片中使用的是 application/x-www-form-urlencoded。这对于我们的 body 来说是非常重要的。只有匹配 Content-Type 的类型才能正确的传递参数信息。
示例的代码使用的是 application/json,所以 body 使用 Json.stringify()进行参数转换,而对于 Content-Type 为 application/x-www-form-urlencoded,需要使用 queryString.stringify()。
Request 中除了 method、headers 与 body,还有以下属性

Request.cache: 请求的缓存模式(default/reload/no-cache)
Request.context: 请求的上下文(audio/image/iframe)
Request.credentials: 请求的证书(omit/same-origin/include)
Request.destination: 请求的内容描述类型
Request.integrity: 请求的 subresource integrity
Request.mode: 请求的模式(cors/no-cors/same-origin/navigate)
Request.redirect: 请求的重定向方式(follow/error/manual)
Request.referrer: 请求的来源(client)
Request.referrerPolicy: 请求的来源政策(no-referrer)
Request.bodyUsed: 声明 body 是否使用在 response 中

请求成功之后,使用.then 来转换数据,使用最多的是 Body.json(),当然你也可以使用以下的几种数据转换类型

Body.arrayBuffer
Body.blob
Body.formData
Body.text

以上是 fetch 请求相关的属性与方法。如果你已经有所了解,那么恭喜你对 fetch 的基本使用已经过关了,下面对 fetch 的使用进行封装。
封装
在实际开发中,url 的 host 都是相同的,不同的是请求的方法名与参数。而对于不同的环境 (debug|release) 请求的方式也可能不同。例如:在 debug 环境中为了方便调试查看请求的参数是否正确,我们会使用 get 来进行请求。所以在封装之前要明确什么是不变的,什么是变化的,成功与失败的响应处理。
经过上面的分析,罗列一下封装需要做的事情。

不变的: host,headers,body.json()
变化的: url,method,body
响应方式: Promise(resolve/reject)

function convertUrl(url, params) {
let realUrl = ApiModule.isDebug?
url + “?” + queryString.stringify(Object.assign({}, params, commonParams)) : url;

if (ApiModule.isDebug) {
console.log(“request: ” + realUrl);
}
return realUrl;
}
首先对 url 与参数 params 进行拼接,如果为 debug 模式将 params 拼接到 url 后。这里使用到了 Object.assign()将 params 与 commonParams 组合成一个 {} 对象。最终通过 queryString.stringify 转化成 string。
ApiModule.isDebug 是原生传递过来的值,对于 Android/IOS 只需传递自己的 ApiModule 即可。
function getMethod() {
return ApiModule.isDebug? “get”: “post”;
}
上述提到的 get 与 post 的请求时机。
const headers = {
Accept: ‘application/json’,
“Content-Type”: “application/x-www-form-urlencoded;charset=UTF-8”
};
在 headers 中 Content-Type 类型为 application/x-www-form-urlencode
function convertBody(params) {
return ApiModule.isDebug? undefined : queryString.stringify(Object.assign({}, params, commonParams));
}
由于 debug 模式使用的是 get 方式,但 get 规定是不能有 body 的,所以这里使用了 undefined 来标识。同时为了匹配 headers 中的 Content-Type,params 的转化必须使用 queryString.stringify;如果接受的是 json, 可以使用 JSON.stringify。
定义完之后 fetch 对外只需接受 params 参数即可。
async function fetchRequest(params){
let body = convertBody(params);
fetch(convertUrl(baseUrl, params),{
method: method,
headers: headers,
body: body
})
.then((response) => response.json())
.then((responseJson) => {
//todo success
})
.catch((error) => {
if (ApiModule.isDebug) {
console.error(“request error: ” + error);
};
//todo error
});
}
fetch 的请求封装完成,但我们的成功与失败的状态并没有通知给调用者,所以还需要一个回调机制。Promise 是一个异步操作最终完成或者失败的对象。它可以接受两个函数 resolve、reject
const p = new Promise((resolve, reject){

//success
resolve(‘success’)
//error
reject(‘error’)
});
//use
p.then(success => {
console.log(success);
}, error => {
console.log(error)
});
将 fetch 请求放入到 Promise 的异步操作中,这样一旦数据成功返回就调用 resolve 函数回调给调用者;失败调用 reject 函数,返回失败信息。而调用者只需使用 Promise 的.then 方法等候数据的回调通知。下面来看下完整的 fetch 封装。
async function fetchRequest(params){
let body = convertBody(params);
return new Promise(function(resolve, reject){
fetch(convertUrl(baseUrl, params),{
method: method,
headers: headers,
body: body
})
.then((response) => response.json())
.then((responseJson) => {
resolve(responseJson);
})
.catch((error) => {
if (ApiModule.isDebug) {
console.error(“request error: ” + error);
};
reject(error);
});
});
}
之后对 fetch 的使用就非常简单了,只需传入需要的参数即可。
fetchRequest({method: “goods.getInfo”, goodsId: 27021599158370074})
.then(res =>{
this.setState({
shareInfo: res.data.shareInfo
});
});
以上是有关 fetch 的全部内容,当然在 React Native 中还有其它的第三方请求库:XMLHttpRequest,同时也支持 WebSockets。感兴趣的也可以去了解一下,相信会有不错的收获。
精选文章
5 分钟吃透 React Native Flexbox
ViewDragHelper 之手势操作神器
tensorflow- 梯度下降, 有这一篇就足够了
七大排序算法总结(java)
拉粉环节:感觉不错的可以来一波关注,扫描下方二维码,关注公众号,及时获取最新知识技巧。

正文完
 0