React Native探索(五)使用fetch進行網路請求

劉望舒發表於2019-02-22

相關文章
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,如下圖所示。

React Native探索(五)使用fetch進行網路請求

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請求”,效果如下所示。

React Native探索(五)使用fetch進行網路請求

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抓包的請求的資訊,如下圖所示。

React Native探索(五)使用fetch進行網路請求
QQ圖片20170606135823.jpg

可以看到請求資料是一個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 進行處理就可以了。

github原始碼

參考資料
Fetch API
fetch-issues-274
MDN Promise教程
ReactNative網路fetch資料並展示在listview中
React Native中的網路請求fetch和簡單封裝
在 JS 中使用 fetch 更加高效地進行網路請求
Using Fetch


歡迎關注我的微信公眾號,第一時間獲得部落格更新提醒,以及更多成體系的Android相關原創技術乾貨。
掃一掃下方二維碼或者長按識別二維碼,即可關注。

React Native探索(五)使用fetch進行網路請求

相關文章