前言
作為前端開發(fā)人員,網(wǎng)絡(luò)請求工具對大家來說肯定不陌生。iOS的AFNetworking,Android的okHttp等。但是對于RN來說,我們最常用到的就是js原生的Fetch請求了。下面的這篇文章我們主要就是來聊聊Fetch請求的簡單使用以及如何封裝一個fetch網(wǎng)絡(luò)請求組件和緩存策略。
直接查看作者fetch請求組件源碼請點(diǎn)擊:https://github.com/guangqiang-liu/react-native-fetch-demo
什么fetch
fetch 是由 whatag 負(fù)責(zé)研發(fā)。與 Ajax 不同的是,它的 API 不是事件機(jī)制,而是采用目前流行的 Promise(MDN Promise) 方式處理
查看ReactNatie官方對于fetch的講解請點(diǎn)擊:http://reactnative.cn/docs/0.49/network.html#content
fetch請求的格式
fetch(url, init)
.then((response) => { // 數(shù)據(jù)解析方式
})
.then((responseData) => { // 獲取到的數(shù)據(jù)處理
})
.catch((error) => { // 錯誤處理
})
.done(); // 結(jié)束鏈?zhǔn)?
在上面的示例中init是一個對象,對象中包含如下屬性:
- method:網(wǎng)絡(luò)請求的方式(GET、POST等)
- headers:網(wǎng)絡(luò)請求的請求頭對象,對象中包含(Accept、Content-Type、token等屬性)
- body:POST請求的請求體對象,即需要往服務(wù)器發(fā)送的數(shù)據(jù)
- mode:跨域設(shè)置(cors, no-cors, same-origin) 不常用
- cache:緩存選項(xiàng)(default, no-store, reload, no-cache, force-cache, or only-if-cached)不常用
response 對象可以有如下幾種解析方式:
- json()
- text()
- arrayBuffer()
- blob()
- formData()
如何使用fetch
GET請求
fetch(url, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
})
.then((response) => response.json()) // json方式解析,如果是text就是response.text()
.then((responseData) => { // 獲取到的數(shù)據(jù)處理
})
.catch((error) => { // 錯誤處理
})
.done()
POST請求
fetch(url, {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
body: JSON.stringify({key1: value1, key2: value2})
})
.then((response) => { // 數(shù)據(jù)解析方式
})
.then((responseData) => { // 獲取到的數(shù)據(jù)處理
})
.catch((error) => { // 錯誤處理
})
.done()
作者封裝的fetch請求組件核心源碼如下
/**
* FetchNetworkDemo
* 作者Git:https://github.com/guangqiang-liu
* 技術(shù)交流群:620792950
* 作者QQ:1126756952
* @guangqiang
*/
/** 基于fetch 封裝的網(wǎng)絡(luò)請求工具類 **/
import {Component} from 'react'
/**
* fetch 網(wǎng)絡(luò)請求的header,可自定義header 內(nèi)容
* @type {{Accept: string, Content-Type: string, accessToken: *}}
*/
let header = {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
/**
* GET 請求時,拼接請求URL
* @param url 請求URL
* @param params 請求參數(shù)
* @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 網(wǎng)絡(luò)請求超時處理
* @param original_promise 原始的fetch
* @param timeout 超時時間 30s
* @returns {Promise.<*>}
*/
const timeoutFetch = (original_fetch, timeout = 30000) => {
let timeoutBlock = () => {}
let timeout_promise = new Promise((resolve, reject) => {
timeoutBlock = () => {
// 請求超時處理
reject('timeout promise')
}
})
// Promise.race(iterable)方法返回一個promise
// 這個promise在iterable中的任意一個promise被解決或拒絕后,立刻以相同的解決值被解決或以相同的拒絕原因被拒絕。
let abortable_promise = Promise.race([
original_fetch,
timeout_promise
])
setTimeout(() => {
timeoutBlock()
}, timeout)
return abortable_promise
}
/**
* 網(wǎng)絡(luò)請求工具類
*/
export default class HttpUtils extends Component {
/**
* 基于fetch 封裝的GET 網(wǎng)絡(luò)請求
* @param url 請求URL
* @param params 請求參數(shù)
* @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(response)
}
}).then(response => {
// response.code:是與服務(wù)器端約定code:200表示請求成功,非200表示請求失敗,message:請求失敗內(nèi)容
if (response) {
return response
} else {
// 非 200,錯誤處理
// alert(response.message)
return response
}
}).catch(error => {
alert(error)
})
}
/**
* 基于fetch 的 POST 請求
* @param url 請求的URL
* @param params 請求參數(shù)
* @returns {Promise}
*/
static postRequrst = (url, params = {}) => {
return timeoutFetch(fetch(url, {
method: 'POST',
headers: header,
body: JSON.stringify(params)
})).then(response => {
if (response.ok) {
return response.json()
} else {
alert('服務(wù)器繁忙,請稍后再試;\r\nCode:' + response.status)
}
}).then(response => {
// response.code:是與服務(wù)器端約定code:200表示請求成功,非200表示請求失敗,message:請求失敗內(nèi)容
if (response && response.code === 200) {
return response
} else {
// alert(response.message)
return response
}
}).catch(error => {
alert(error)
})
}
}
作者的fetch網(wǎng)絡(luò)請求組件涵蓋如下功能:
- 發(fā)送GET網(wǎng)絡(luò)請求
- 發(fā)送POST網(wǎng)絡(luò)請求
- GET請求數(shù)據(jù)緩存策略
- 請求超時處理
fetch網(wǎng)絡(luò)請求組件待完成事項(xiàng):
- 文件、圖片網(wǎng)絡(luò)上傳
- 文件下載
- 待補(bǔ)充
總結(jié)
總之使用fetch發(fā)送網(wǎng)絡(luò)請求還是挺簡單的。fetch請求中使用到promise對象和函數(shù)柯里化概念。如果同學(xué)們對于promise和柯里化不是很熟悉,建議先了解下概念及使用方法。建議同學(xué)們直接下載作者的fetch請求組件源碼進(jìn)行調(diào)試學(xué)習(xí)。fetch請求組件源碼地址:https://github.com/guangqiang-liu/react-native-fetch-demo。 如果感覺文章對你有幫助,請給個 star 關(guān)注 謝謝。
福利時間
- 作者React Native開源項(xiàng)目OneM地址(按照企業(yè)開發(fā)標(biāo)準(zhǔn)搭建框架設(shè)計(jì)開發(fā)):https://github.com/guangqiang-liu/OneM (歡迎小伙伴們 star)
- 作者簡書主頁:包含50多篇RN開發(fā)相關(guān)的技術(shù)文章http://www.itdecent.cn/u/023338566ca5 (歡迎小伙伴們:多多關(guān)注,多多點(diǎn)贊)
- 作者React Native QQ技術(shù)交流群:620792950 歡迎小伙伴進(jìn)群交流學(xué)習(xí)
- 友情提示:在開發(fā)中有遇到RN相關(guān)的技術(shù)問題,歡迎小伙伴加入交流群(620792950),在群里提問、互相交流學(xué)習(xí)。交流群也定期更新最新的RN學(xué)習(xí)資料給大家,謝謝支持!