作为前端开发人员,网络请求工具对大家来说肯定不陌生。iOS的AFNetworking,Android的okHttp等。但是对于RN来说,我们最常用到的就是js原生的Fetch请求了。
React Native提供了和web标准一致的Fetch API,用于满足开发者访问网络的需求。如果你之前使用过XMLHttpRequest
(即俗称的ajax)或是其他的网络API,那么Fetch用起来将会相当容易上手。这篇文档只会列出Fetch的基本用法,并不会讲述太多细节,你可以使用你喜欢的搜索引擎去搜索fetch api
关键字以了解更多信息。
fetch使用链式调用的方式来进行操作,fetch的基本格式
fetch(url , fetchOptions)
.then((response) => {
...//数据解析方式
})
.then((responseData) => {
...//获取到的数据处理
})
.catch((error) => {
...//错误处理
})
.done(); //结束链式
fetch(url)为发起网络请求的最简单的写法,只传入一个参数,默认的为GET方式请求,将网址作为参数传入fetch 的方法,如:
fetch('https://mywebsite.com/mydata.json')
fetch还有可选的第二个参数,即示例中的fetchOptions,是一个对象,对象中包含如下属性
let fetchOptions = {
method:'POST',
headers:{
'Accept':'application/json',
'Content-Type':'application/json',
},
body:JSON.stringify({
firstParam:'yourValue',
secondParam:'yourOtherValue',
})
};
fetch(url , fetchOptions);
1、headers请求头遵循http协议规范,通常设置Accept、Content-Type属性。
Accept:希望接受的数据类型
Content-Type:发送的实体数据的数据类型
headers: {
'Accept' : 'application/json',
'Content-Type' : 'application/json',
}
2、body的传入参数有三种方式:
方式一:不推荐,可能在某些服务器无法识别。
JSON.stringify({key:value1 , key2:value2 , ...})
方式二:传统的form格式
'key1 = value1 & key2 = value2'
方式三:使用FormData
let formData = new FormData();
formData.append("key1" , "value1");
formData.append("key2" , "value2");
3、mode:控制属否允许跨域:
fetch封装源码核心 HttpUtils.js
/**
* Created by gongchenghui on 2018/4/19.
*/
/** 基于fetch 封装的网络请求工具类 **/
import { Component } from "react";
/**
* fetch 网络请求的header,可自定义header 内容
* @type {{Accept: string, Content-Type: string, accessToken: *}}
*/
let header = {
Accept: "application/json",
"Content-Type": "application/json"
};
/**
* GET 请求时,拼接请求URL
* @param url 请求URL
* @param params 请求参数
* @returns {*}
*/
const handleUrl = (url) => (params) => {
if (params) {
let paramsArray = [];
Object.keys(params).forEach((key) =>
paramsArray.push(key + "=" + encodeURIComponent(params[key]))
);
if (url.search(/\?/) === -1) {
typeof params === "object" ? (url += "?" + paramsArray.join("&")) : url;
} else {
url += "&" + paramsArray.join("&");
}
}
return url;
};
/**
* fetch 网络请求超时处理
* @param original_promise 原始的fetch
* @param timeout 超时时间 30s
* @returns {Promise.<*>}
*/
const timeoutFetch = (originalFetch, timeout = 30000) => {
let timeoutBlock = () => {};
let timeoutPromise = new Promise((resolve, reject) => {
timeoutBlock = () => {
// 请求超时处理
reject("timeout promise");
};
});
// Promise.race(iterable)方法返回一个promise
// 这个promise在iterable中的任意一个promise被解决或拒绝后,立刻以相同的解决值被解决或以相同的拒绝原因被拒绝。
let abortablePromise = Promise.race([originalFetch, timeoutPromise]);
setTimeout(() => {
timeoutBlock();
}, timeout);
return abortablePromise;
};
/**
* 网络请求工具类
*/
export default class HttpUtils extends Component {
/**
* 基于fetch 封装的GET 网络请求
* @param url 请求URL
* @param params 请求参数
* @returns {Promise}
*/
static getRequest = (url, params = {}) => {
return timeoutFetch(
fetch(handleUrl(url)(params), {
method: "GET",
headers: header
})
)
.then((response) => {
if (response.ok) {
return response.json();
} else {
// alert("服务器繁忙,请稍后再试!");
}
})
.then((response) => {
// response.code:是与服务器端约定code:200表示请求成功,非200表示请求失败,message:请求失败内容
if (response) {
return response;
} else {
// 非 200,错误处理
return response;
}
})
.catch((error) => {});
};
/**
* 基于fetch 的 POST 请求
* @param url 请求的URL
* @param params 请求参数
* @returns {Promise}
*/
static postRequrst = (url, params = {}) => {
let formData = new FormData();
Object.keys(params).forEach((key) => formData.append(key, params[key]));
return timeoutFetch(
fetch(url, {
method: "POST",
headers: header,
body: formData
})
)
.then((response) => {
if (response.ok) {
return response.json();
} else {
// alert("服务器繁忙,请稍后再试;\r\nCode:" + response.status);
}
})
.then((response) => {
// response.code:是与服务器端约定code:200表示请求成功,非200表示请求失败,message:请求失败内容
if (response && response.code === 200) {
return response;
} else {
return response;
}
})
.catch((error) => {
// alert("当前网络不可用,请检查网络设置!");
});
};
}
方法输出 HttpExtension.js:
/**
* Created by gongchenghui on 2018/4/19.
*/
/** 网络请求工具类的拓展类,便于后期网络层修改维护 **/
import HttpUtils from "./HttpUtils";
import { dataCache } from "../cache";
// const API_URL = "https://api-m.mtime.cn";
// const API_URL = "http://apimanage.58corp.com/";
/**
* GET
* 从缓存中读取数据
* @param isCache: 是否缓存
* @param url 请求url
* @param params 请求参数
* @param isCache 是否缓存
* @param callback 是否有回调函数
* @returns {value\promise}
* 返回的值如果从缓存中取到数据就直接换行数据,或则返回promise对象
*/
const fetchData = (isCache, type) => (url, params, callback) => {
url = `${url}`;
// url = `${API_URL}${url}`;
const fetchFunc = () => {
let promise =
type === "get" ? HttpUtils.getRequest(url, params) : HttpUtils.postRequrst(url, params);
if (callback && typeof callback === "function") {
promise.then((response) => {
return callback(response);
});
}
return promise;
};
return dataCache(url, fetchFunc, isCache);
};
/**
* GET 请求
* @param url
* @param params
* @param source
* @param callback
* @returns {{promise: Promise}}
*/
const getFetch = fetchData(false, "get");
/**
* POST 请求
* @param url
* @param params
* @param callback
* @returns {{promise: Promise}}
*/
const postFetch = fetchData(false, "post");
/**
* GET 请求,带缓存策略
* @param url
* @param params
* @param callback
* @returns {{promise: Promise}}
*/
const getFetchFromCache = fetchData(true, "get");
export { getFetch, postFetch, getFetchFromCache };
缓存设置:
/**
* FetchNetworkDemo
* Created by gongchenghui on 2018/4/19
*/
import store from "react-native-simple-store";
/**
* @param key:key为url的Path
* @param fetchFunc:回调函数
* @param isCache:是否需要缓存
* @returns {value}
*/
const dataCache = (key, fetchFunc, isCache) => {
// 不缓存,
if (!isCache) {
return fetchFunc();
}
// 需要缓存
return store.get(key).then((value) => {
if (value) {
// 如果在缓存中找到数据,则返回缓存中的数据
return value;
} else {
// 如果在缓存中取不到数据,则从网络请求中获取数据,并将获取到的数据缓存下来
return fetchFunc().then((value) => {
value ? store.save(key, value) : null;
return value;
});
}
});
};
export { dataCache };
使用:
import WEBAPP from "@/"import WEBAPP from "@/"
...
WEBAPP.getFetch(url, param).then((response) => {
...
});
WEBAPP.postFetch(url, param).then((response) => {
...
});
...