1. 程式人生 > >React Native入門(八)之網路請求Fetch

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,一個 Promiseresolve時會回傳 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: 請求使用的方法,如 GETPOST
  • headers: 請求的頭資訊,形式為 Headers 物件或 ByteString。
  • body: 請求的 body 資訊:可能是一個 Blob、BufferSource、FormData、URLSearchParams 或者 USVString 物件。注意 GET 或 HEAD 方法的請求不能包含 body 資訊
  • mode: 請求的模式,如 corsno-cors 或者 same-origin
  • credentials: 請求的 credentials,如 omitsame-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表示請求成功則為true
  • headers (Headers) - 返回頭部資訊,下面詳細介紹
  • url (String) - 請求的地址

方法:

  • text() - 以string的形式生成請求text
  • json() - 生成JSON.parse(responseText)的結果
  • blob() - 生成一個Blob
  • arrayBuffer() - 生成一個ArrayBuffer
  • formData() - 生成格式化的資料,可用於其他的請求

其他方法:

  • clone()
  • Response.error()
  • Response.redirect()

上邊就是Fetch常用的API,其他的API可以參考Fetch_API,也就是上邊的網站!