React Native入門(八)之網路請求Fetch
前言
最近有些事情要忙,RN相關的內容沒有更新,現在就來了解一下RN中進行網路請求相關的內容!
介紹
React Native提供了和web標準一致的Fetch API,用於滿足開發者訪問網路的需求。
關於Fetch API的相關內容,可以到下邊網站了解:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
我們這先大致說一下在RN中使用Fetch API 進行網路請求的例子,然後再去了解Fecth的相關內容!
使用Fetch
Fetch API 提供一個fetch()
方法,要從任意地址獲取內容的話,只需簡單地將網址作為引數傳遞給fetch方法即可。
fetch('https://facebook.github.io/react-native/movies.json')
Fetch API 是基於 Promise
設計,那麼關於 Promise
的內容可以參考下面的教程:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
這裡簡單提一下:
我們知道網路請求是一個天然的非同步操作,Fetch 方法會返回一個Promise
,這種模式可以簡化非同步風格的程式碼。Promise
物件是一個返回值的代理,它允許你為非同步操作的成功或失敗指定處理方法。 這使得非同步方法可以像同步方法那樣返回值:非同步方法會返回一個包含了原返回值的promise
Promise
有兩個重要的方法,分別是resolve
方法和reject
方法。如果非同步操作成功,則用resolve
方法將Promise
物件的狀態變為“成功”(即從pending變為resolved);如果非同步操作失敗,則用reject
方法將狀態變為“失敗”(即從pending變為rejected)。
好了,知道了這些之後,我們來說一下如果處理網路請求返回的結果!
Fetch 方法會返回一個Promise
,一個 Promise
,resolve
時會回傳 Response
物件,也就是說請求成功,會回傳一個Response
物件,這個Response
物件就包含了所有返回結果的資訊!
好,下面看一個例子,也是RN中文網的例子,這裡做了一些改動!
首先,我們在瀏覽器看一下網路請求到的內容:
{
"title": "The Basics - Networking",
"description": "Your app fetched this from a remote endpoint!",
"movies": [
{ "title": "Star Wars", "releaseYear": "1977"},
{ "title": "Back to the Future", "releaseYear": "1985"},
{ "title": "The Matrix", "releaseYear": "1999"},
{ "title": "Inception", "releaseYear": "2010"},
{ "title": "Interstellar", "releaseYear": "2014"}
]
}
這個一個請求到一些電影資訊的json資料。
這裡我們使用fetch傳送網路請求,然後將得到的json資料使用列表展示出來,下面看一下程式碼:
class NetText extends Component {
constructor(props) { //構造器
super(props);
this.state = { //定義的三個狀態
title: '',
description: '',
movies: ''
};
}
//列表點選事件
itemClick(item, index) {
alert('點選了第' + index + '項,電影名稱:' + item.title + '上映年份:' + item.releaseYear);
}
//FlatList的key
_keyExtractor = (item, index) => index;
//子item渲染
_renderItem = ({item, index}) => {
return (
<TouchableOpacity
activeOpacity={0.5}
onPress={this.itemClick.bind(this, item, index)}>
//這裡index為奇偶數給不同的背景
<View style={[WebTestStyles.item, {backgroundColor: index % 2 == 0 ? 'lightgray' : 'whitesmoke'}]}>
<Text style={WebTestStyles.itemTitle}>{item.title}</Text>
<Text style={WebTestStyles.itemYear}>上映年份:{item.releaseYear}</Text>
</View>
</TouchableOpacity>
);
}
//列表分割線
_itemDivide = () => {
return (
<View style={{height: 1, backgroundColor: 'dimgray'}}/>
);
}
//getMoviesFromApiAsync() {
_fetchData = () => {
fetch('https://facebook.github.io/react-native/movies.json')
.then((response) => response.json())//把response轉為json格式
.then((jsondata) => { //上面的轉好的json
//alert(jsondata.movies[0].title);
this.setState({ //將獲取到的資料更新到state中
title: jsondata.title,
description: jsondata.description,
movies: jsondata.movies,
})
})
.catch((error) => {
console.error(error);
});
};
render() {
return (
<View style={WebTestStyles.container}>
<Text style={WebTestStyles.title}>{this.state.title}</Text>
<Text style={WebTestStyles.description}>{this.state.description}</Text>
<FlatList //列表元件
style={{marginTop: 20}}
data={this.state.movies}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
ItemSeparatorComponent={this._itemDivide}/>
<Button title="請求網路" onPress={this._fetchData}/>
</View>
);
}
}
;
const WebTestStyles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column'
},
title: {
fontSize: 20,
fontWeight: 'bold',
alignSelf: 'center'
},
description: {
fontSize: 12,
alignSelf: 'center'
},
item: {
padding: 10
},
itemTitle: {
fontSize: 18,
fontWeight: 'bold'
},
itemYear: {
fontSize: 16,
}
})
然後看一下效果:
程式碼的話,基本上沒有什麼好說的,就是點選一個按鈕去請求網路,然後拿到json格式的資料,兩個文字欄位,一個數組,然後把陣列設定為FlatList的data,將電影以列表形式展示!
Fetch相關API
請求引數的設定
上面我們在請求網路的時候,只是用fetch(url)
這樣的形式,我們也可以設定其他的引數來請求網路,如下所示:
method
: 請求使用的方法,如GET
、POST
。headers
: 請求的頭資訊,形式為 Headers 物件或 ByteString。body
: 請求的 body 資訊:可能是一個 Blob、BufferSource、FormData、URLSearchParams 或者 USVString 物件。注意 GET 或 HEAD 方法的請求不能包含 body 資訊。mode
: 請求的模式,如cors
、no-cors
或者same-origin
。credentials
: 請求的 credentials,如omit
、same-origin
或者include
。cache
: 請求的 cache 模式:default
,no-store
,reload
,no-cache
,force-cache
, 或者only-if-cached
。
類似這樣:
fetch('https://mywebsite.com/endpoint/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
firstParam: 'yourValue',
secondParam: 'yourOtherValue',
})
})
如果你的伺服器無法識別上面POST的資料格式,那麼可以嘗試傳統的form格式,示例如下:
fetch('https://mywebsite.com/endpoint/', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'key1=value1&key2=value2'
})
這個得話,就需要和做後臺的同事提前溝通好就行了!
自定義Header
關於請求頭Header的話,還可以通過 Headers() 建構函式來建立一個你自己的 headers 物件。
var myHeaders = new Headers();
myHeaders.append("Content-Type", "text/plain");
myHeaders.append("Content-Length", content.length.toString());
myHeaders.append("X-Custom-Header", "ProcessThisImmediately");
也可以傳一個多維陣列或者物件字面量:
myHeaders = new Headers({
"Content-Type": "text/plain",
"Content-Length": content.length.toString(),
"X-Custom-Header": "ProcessThisImmediately",
});
自定義Request
除了上面的用法,我們還可以通過使用Request()
建構函式來建立一個request
物件,然後再作為引數傳給fetch()
。這裡就相當於把url和header或者其他的引數綜合起來!
比如:
var url='https://mywebsite.com/endpoint/';
var myOptions = { method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default' };
var myRequest = new Request(url, myOptions );
fetch(myRequest)
.then()
...
Response
屬性:
status (number)
- HTTP請求結果引數,在100–599 範圍statusText (String)
- 伺服器返回的狀態報告ok (boolean)
- 如果返回200表示請求成功則為trueheaders (Headers)
- 返回頭部資訊,下面詳細介紹url (String)
- 請求的地址
方法:
text()
- 以string的形式生成請求textjson()
- 生成JSON.parse(responseText)的結果blob()
- 生成一個BlobarrayBuffer()
- 生成一個ArrayBufferformData()
- 生成格式化的資料,可用於其他的請求
其他方法:
clone()
Response.error()
Response.redirect()
上邊就是Fetch常用的API,其他的API可以參考Fetch_API,也就是上邊的網站!