Demo: https://github.com/YouCii/RNDemo
转到 RN 之后还是不自主地按照 android 的方式搭框架, 今天把 fetch 封装到了 HttpUtils 里.
import JsonUtils from "./JsonUtils";
import EncodeUtils from "./EncodeUtils";
/**
* 返回Promise对象的网络请求工具类
* 封装了请求超时/部分错误提示等
*/
export default class HttpUtils {
/**
* 开启GET请求
* @param url 请求地址
* @param params GET请求参数,Map
* @return promise对象
*/
static startGetRequest(url: String, params: Map) {
if (params != null && params.size !== 0) {
url += "?";
params.forEach((value, key) => {
url += (key + "=" + value + "&");
});
url = url.substr(0, url.length - 1)
}
return Promise.race([fetch(url, {
method: "Get",
credentials: "include"
}), new Promise(((resolve, reject) => {
setTimeout(() => reject(new Error('请求超时')), timeOut)
}))])
.then((response: Response) => checkStatus(response))
.then((response: Response) => {
return response.text()
})
.then((responseText: String) => {
return JsonUtils.stringToJson(responseText);
})
}
/**
* 开启POST请求(测试没有问题)
* @param url 请求地址
* @param params POST请求参数,Map
* @return promise对象
*/
static startPostRequest = (url: String, params: Map) => {
let formData = new FormData();
if (params != null && params.size !== 0) {
params.forEach((value, key) => {
formData.append(key, value);
})
}
return Promise.race([fetch(url, {
method: "POST",
credentials: "include",
body: formData,
}), new Promise((resolve, reject) => {
setTimeout(() => reject(new Error('请求超时')), timeOut)
})])
.then((response: Response) => checkStatus(response))
.then((response: Response) => {
return response.text()
})
.then((responseText: String) => {
// 是否需要解密之类的判断
if (responseText.indexOf("\"data\"") === -1
&& responseText.indexOf("\"message\"") === -1
&& responseText.indexOf("\"msg\"") === -1) {
responseText = EncodeUtils.decodeBase64Content(responseText);
}
return JsonUtils.stringToJson(responseText);
})
}
}
/**
* 请求超时时间
*/
const timeOut = 5 * 1000;
/**
* 解决fetch不提示某些错误的问题
*/
function checkStatus(response) {
if (response.ok || (response.status >= 200 && response.status < 300)) {
return response;
}
throw new Error(response.statusText); // 或者 reject(new Error('test'));
}
上面是使用 response.text() 拿到了回调字符串, 如果回调肯定是一个无需额外处理的 json 的话, 可以使用 response.json() 直接拿到实体类.
HttpUtils 的具体使用:
let params = new Map();
params.set('start', 0);
params.set('count', toSelectNum);
HttpUtils.startGetRequest("https://api.douban.com/v2/movie/top250", params)
.then(responseJson => {
// responseJson.subjects[0].images.large 就是实体类内的数据
Image.getSize(responseJson.subjects[0].images.large, (width, height) => {
this.setState({
imageRadio: height / width,
topMovieResponse: responseJson,
});
})
})
.catch(error => {
AlertUtils.showSimpleAlert('请求失败' + error);
});
附 Base64加解密工具类
import {Buffer} from "buffer" // npm install --save buffer
/**
* Base64加解密
*/
export default class EncodeUtils {
/**
* 加密
*/
static encodeBase64Content(content) {
return new Buffer(content).toString('base64')
}
/**
* 解密
*/
static decodeBase64Content(base64Content) {
return new Buffer(base64Content, 'base64').toString();
}
}
Json解析工具类
export default class JsonUtils {
/**
* 字符串转json
*/
static stringToJson(data) {
return JSON.parse(data);
}
/**
* json转字符串
*/
static jsonToString(data) {
return JSON.stringify(data);
}
/**
* map转换为json
*/
static mapToJson(map) {
return JSON.stringify(strMapToObj(map));
}
/**
* json转换为map
*/
static jsonToMap(jsonStr) {
return objToStrMap(JSON.parse(jsonStr));
}
}
/**
* map转化为对象(map所有键都是字符串,可以将其转换为对象)
*/
function strMapToObj(strMap) {
let obj = Object.create(null);
for (let [k, v] of strMap) {
obj[k] = v;
}
return obj;
}
/**
* 对象转换为Map
*/
function objToStrMap(obj) {
let strMap = new Map();
for (let k of Object.keys(obj)) {
strMap.set(k, obj[k]);
}
return strMap;
}