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

相关文章
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',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 进行处理就可以了。

github源码

参考资料
Fetch API
fetch-issues-274
MDN Promise教程
ReactNative网络fetch数据并展示在listview中
React Native中的网络请求fetch和简单封装
在 JS 中使用 fetch 更加高效地进行网络请求
Using Fetch

欢迎关注我的微信公众号,第一时间获得博客更新提醒,以及更多成体系的Android相关原创技术干货。
扫一扫下方二维码或者长按识别二维码,即可关注。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom