相關文章
React Native探索系列
前言
React Native可以使用多種方式來進行網路請求,比如fetch、XMLHttpRequest以及基於它們封裝的框架,fetch可以說是替代XMLHttpRequest的產物,這一節我們就來學習fetch的基本用法。
1.get請求
fetch API是基於 Promise 設計的,因此瞭解Promise也是有必要的,推薦閱讀MDN Promise教程 。
get請求訪問淘寶IP庫
我們先從最基礎的get請求開始,get請求的地址為淘寶IP地址庫,裡面有訪問介面的說明。請求程式碼如下所示。
fetch(`http://ip.taobao.com/service/getIpInfo.php?ip=59.108.51.32`, {
method: `GET`,
headers: {
`Content-Type`: `application/json`
}
}).then((response) => {//1
console.log(response);
}).catch((err) => {//2
console.error(err);
});複製程式碼
其中method用於定義請求的方法,這裡不用寫method也可以,fetch預設的method就是GET。fetch方法會返回一個Promise物件,這個Promise物件中包含了響應資料response,也就是註釋1處的response引數。在註釋1處呼叫then方法將response列印在控制檯Console中,then方法同樣也會返回Promise物件,Promise物件可以進行鏈式呼叫,這樣就可以通過多次呼叫then方法對響應資料進行處理。在註釋2處通過catch方法來處理請求網路錯誤的情況。
除了上面這一種寫法,我們還可以使用Request,如下所示。
let request = new Request(`http://liuwangshu.cn`, {
method: `GET`,
headers: ({
`Content-Type`: `application/json`
})
});
fetch(request).then((response) => {
console.log(response);
}).catch((err) => {
console.error(err);
});複製程式碼
我們先建立了Request物件,並對它進行設定,最後交給fetch處理。
為了驗證fetch的get請求,需要新增觸發get請求的程式碼邏輯,如下所示。
import React, {Component} from `react`;
import {AppRegistry, View, Text, StyleSheet, TouchableHighlight} from `react-native`;
class Fetch extends Component {
render() {
return (
<View style={styles.container}>
<TouchableHighlight
underlayColor=`rgb(210,260,260)`
style={{padding: 10, marginTop: 10, borderRadius: 5,}}
onPress={this.get}
>
<Text >get請求</Text>
</TouchableHighlight>
</View>
);
}
get() {
fetch(`http://ip.taobao.com/service/getIpInfo.php?ip=59.108.51.32`, {
method: `GET`,
}).then((response) => {
console.log(response);//1
}).catch((err) => {//2
console.error(err);
});
}
}
const styles = StyleSheet.create({
container: {
alignItems: `center`,
}
});
AppRegistry.registerComponent(`FetchSample`, () => Fetch);複製程式碼
這裡新增了一個TouchableHighlight,並定義了它的點選事件,一旦點選就會觸發get方法請求網路。執行程式點選“get請求”,這時在控制檯Console中就會顯示回撥的Response物件的資料,它包含了響應狀態(status)、頭部資訊(headers)、請求的url(url)、返回的資料等資訊。這次請求的響應狀態status為200,返回的資料是JSON格式的,用Charles抓包來檢視返回的JSON,如下圖所示。
Response物件解析
Response物件中包含了多種屬性:
- status (number) : HTTP請求的響應狀態行。
- statusText (String) : 伺服器返回的狀態報告。
- ok (boolean) :如果返回200表示請求成功,則為true。
- headers (Headers) : 返回頭部資訊。
- url (String) :請求的地址。
Response物件還提供了多種方法:
- formData():返回一個帶有FormData的Promise。
- json() :返回一個帶有JSON物件的Promise。
- text():返回一個帶有文字的Promise。
- clone() :複製一份response。
- error():返回一個與網路相關的錯誤。
- redirect():返回了一個可以重定向至某URL的response。
- arrayBuffer():返回一個帶有ArrayBuffer的Promise。
- blob() : 返回一個帶有Blob的Promise。
接下來對返回的Response進行簡單的資料處理,如下所示。
get() {
fetch(`http://ip.taobao.com/service/getIpInfo.php?ip=59.108.23.12`, {
method: `GET`,
headers: {
`Content-Type`: `application/json`
}
}).then((response) => response.json())//1
.then((jsonData) => {//2
let country = jsonData.data.country;
let city = jsonData.data.city;
alert("country:" + country + "-------city:" + city);
});
}複製程式碼
訪問淘寶IP地址庫會返回JSON資料,因此在註釋1處呼叫response的json方法,將response轉換成一個帶有JSON物件的Promise,也就是註釋2處的jsonData。最後取出jsonData中資料並展示在Alert中,這裡data是一個物件,如果它是一個物件陣列我們可以這樣獲取它的資料:
let country=jsonData.data[0].country;複製程式碼
點選“get請求”,效果如下所示。
2.post請求
post請求的程式碼如下所示。
post() {
fetch(`http://ip.taobao.com/service/getIpInfo.php`, {
method: `POST`,//1
headers: {
`Content-Type`: `application/json`,
},
body: JSON.stringify({//2
`ip`: `59.108.23.12`
})
}).then((response) => response.json())
.then((jsonData) => {
let country = jsonData.data.country;
let city = jsonData.data.city;
alert("country:" + country + "-------city:" + city);
});
}複製程式碼
在註釋1處將method改為POST,在註釋2處新增請求的body。與get請求類似,這裡也新增一個觸發事件來進行post請求,當點選“post請求”時,檢視Charles抓包的請求的資訊,如下圖所示。
可以看到請求資料是一個GSON字串,因為淘寶IP庫並不支援此型別的POST請求,所以不會返回我們需要的地理資訊資料。
3.簡單封裝fetch
如果每次請求網路都要設定method、headers、body等資料,同時還要多次呼叫then方法對返回資料進行處理,顯然很麻煩,下面就對上面例子中的get和post請求做一個簡單的封裝。
首先建立一個FetchUtils.js,程式碼如下所示。
import React, {Component} from `react`;
class FetchUtils extends React.Component {
static send(method, url, data, callback) {
let request;
if (method === `get`) {
request = new Request(url, {
method: `GET`,
headers: ({
`Content-Type`: `application/json`
})
});
} else if (method === `post`) {
request = new Request(url, {
method: `POST`,
headers: ({
`Content-Type`: `application/json`
}),
body: JSON.stringify(data)
});
}
fetch(request).then((response) => response.json())
.then((jsonData) => {
callback(jsonData);//1
});
}
}
module.exports = FetchUtils;複製程式碼
在FetchUtils中定義了send方法,對GET和POST請求做了區分處理,並在註釋1處通過callback將響應資料response回撥給呼叫者。
最後呼叫FetchUtils的send方法,分別進行GET和POST請求:
let FetchUtils=require(`./FetchUtils`);
...
sendGet() {
FetchUtils.send(`get`, `http://ip.taobao.com/service/getIpInfo.php?ip=59.108.23.16`, ``,
jsonData => {
let country = jsonData.data.country;
let city = jsonData.data.city;
alert("country:" + country + "-------city:" + city);
})
}
sendPost() {
FetchUtils.send(`post`, `http://ip.taobao.com/service/getIpInfo.php`, {`ip`: `59.108.23.16`},
jsonData => {
let country = jsonData.data.country;
let city = jsonData.data.city;
alert("country:" + country + "-------city:" + city);
})
}複製程式碼
這樣我們使用Fetch訪問網路時,只需要傳入需要的引數,並對返回的jsonData 進行處理就可以了。
參考資料
Fetch API
fetch-issues-274
MDN Promise教程
ReactNative網路fetch資料並展示在listview中
React Native中的網路請求fetch和簡單封裝
在 JS 中使用 fetch 更加高效地進行網路請求
Using Fetch
歡迎關注我的微信公眾號,第一時間獲得部落格更新提醒,以及更多成體系的Android相關原創技術乾貨。
掃一掃下方二維碼或者長按識別二維碼,即可關注。