React Native 探索(五)使用 fetch 进行网络请求

前言

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://iacblog.com', {
            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,如下图所示。
VYsHXT.jpg

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请求”,效果如下所示。
VYsqnU.jpg

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 抓包的请求的信息,如下图所示。

VYs7cV.jpg

可以看到请求数据是一个 JSON 字符串,因为淘宝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 进行处理就可以了。

本作品采用《CC 协议》,转载必须注明作者和本文链接

By: Laravel-China 宁泽林
MyBlog: nizer.in

讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!