ReactNative开发之网络请求

在ReactNative中,使用fetch实现网络请求。fetch同XMLHttpRequest非常类似,是一个封装程度更高的网络API,使用起来很简洁,因为使用了Promise。

Promise是异步编程的一种解决方案,比传统的解决方案--回调函数和事件--更合理、更强大。ES6将其写进了语言标准,统一了用法,原生提供了Promise对象。简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。

Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成)、Rejected(已失败)。Promise实例生成以后,可以分别指定“完成”和“失败”状态的回调函数。实现方式:链式调用方法,fetch中使用的就是该特性。

语法:
  fetch(参数)
  .then(完成的回调函数)
  .catch(失败的回调函数)

  fetch(url, opts)
  .then((response) => {
    // 网络请求成功执行的回调函数,得到响应对象,通过response可以获取请求的数据。例如:json、text等等
    return response.text();
    // return response.json();
  })
  .then((responseData) => {
    // 处理请求得到的数据
  })
  .catch((error) => {
    // 网络请求失败执行该回调函数,得到错误信息
  })

在POST请求中需要用到一个FormData的概念。

FormData

Web应用中频繁使用的一项功能就是表单数据的序列化,XMLHttpRequest2级定义了FormData类型,FormData主要用于实现序列化表单以及创建与表单格式相同的数据。

var data = new FormData();
data.append("name", "xiaoming");
append方法接收两个参数:键和值。分别对应表单字段的名字和字段中包含的值,添加多个键值对。

在jQuery中,“key1=value1&key2=value2”作为参数传入对象框架会自动封装成FormData形式。在Fetch中进行post请求时,需要自动创建FormData对象传给body。

示例1 - 网络请求的用法

import React, { Component } from 'react';
import {
  StyleSheet,
  Text,
  View,
  TouchableOpacity
} from 'react-native';

// GET请求
function getRequest(url) {
  var opts = {
    method: "GET"
  };

  fetch(url, opts)
  .then((response) => {
    return response.text(); // 返回一个带文本的对象
  })
  .then((responseText) => {
    alert(responseText);
  })
  .catch((error) => {
    alert(error);
  })
}

// POST请求
function postRequest(url) {
  // 将“key1=value1&key2=value2”封装成FormData形式
  let formData = new FormData();
  formData.append("username", "xiaoming");
  formData.append("password", "123");

  var opts = {
    method: "POST",
    body: formData
  };

  fetch(url, opts)
  .then((response) => {
    return response.text(); // 返回一个带文本的对象
  })
  .then((responseText) => {
    alert(responseText);
  })
  .catch((error) => {
    alert(error);
  })
}

var GetData = React.createClass({
  render: function () {
    return(
      <View style={styles.container}>
        <TouchableOpacity onPress={getRequest.bind(this, "http://demo.php?username=小&password=123")}>
          <View style={styles.btn}>
            <Text>GET</Text>
          </View>
        </TouchableOpacity>
        <TouchableOpacity opPress={postRequest.bind(this, "http://demo.php")}>
          <View style={styles.btn}>
            <Text>POST</Text>
          </View>
        </TouchableOpacity>
      </View>
    );
  }
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 30,
    backgroundColor: "cyan",
    flexDirection: "row",
    justifyContent: "space-around",
    alignItems: "center"
  },
  btn: {
    width: 60,
    height: 30,
    borderWidth: 1,
    borderRadius: 3,
    borderColor: "black",
    backgroundColor: "yellow",
    justifyContent: "center",
    alignItems: "center"
  },
});

module.exports = GetData;

运行结果:

运行结果.png

示例2 - 网络请求获取列表数据

import React, { Component } from 'react';
import {
  StyleSheet,
  Text,
  View,
  TouchableOpacity,
  ListView,
  Image
} from 'react-native';

/*
  展示电影列表

  逻辑:未获取数据时,显示等待页面;获取数据时,显示电影列表页面
  需要给state添加一个属性,用于记录数据获取状态
*/

var REQUEST_URL = "https://raw.githubusercontent.com/facebook/react-native/master/docs/MoviesExample.json";

var MovieList = React.createClass({
  // 设置初始状态值
  getInitialState: function () {
    // 定义一个dataSource对象
    var ds = new ListView.DataSource({
      rowHasChanged: (oldRow, newRow) => oldRow != newRow
    });
    return {
      // 数据是否下载成功的标识
      loaded: false,
      dataSource: ds
    };
  },
  // 请求数据
  getData: function () {
      fetch(REQUEST_URL)
      .then((response) => {
        return response.json();
      })
      .then((responseData) => {
        // 刷新组件,重新渲染组件,展示ListView
        // 得到新的数据,更新dataSource
        this.setState({
          loaded: true,
          dataSource: this.state.dataSource.cloneWithRows(responseData.movies)
        });
      })
      .catch((error) => {
        alert(error);
      })
  },

  render: function () {
    // 如果未请求到数据,提示“加载等待”页面
    if (!this.state.loaded) {
      return this.renderLoadingView();
    }

    // 电影列表
    return (
      <ListView
        style={styles.listView}
        dataSource={this.state.dataSource}
        initialListSize={10}
        renderHeader={this._renderHeader}
        renderRow={this._renderRow}
        renderSeparator={this._renderSeparator}
      />
    );
  },
  // 组件挂载完成 生命周期函数
  componentDidMount: function () {
    // 组件挂载后,开始请求数据
    this.getData();
  },

  // 等待加载页面
  renderLoadingView: function () {
    return(
      <View style={styles.loadingContainer}>
        <Text style={styles.loadingText}>Loading movies ...</Text>
      </View>
    );
  },

 // 渲染行
 _renderRow: function (movie) {
   return (
     <View style={styles.rowContainer}>
       <Image style={styles.thumbnail} source={{uri:movie.posters.thumbnail}}/>
       <View style={styles.textContainer}>
         <Text style={styles.title}>{movie.title}</Text>
         <Text style={styles.year}>{movie.year}</Text>
       </View>
     </View>
   );
 },

 // 渲染头部
 _renderHeader: function () {
   return (
     <View style={styles.header}>
       <Text style={styles.header_text}>Movie List</Text>
       <View style={styles.headerSeparator}></View>
     </View>
   );
 },

 // 渲染分割线
 _renderSeparator: function (sectionID: number, rowID: number) {
   var style = {
     height: 1,
     backgroundColor: "#CCC"
   };

   return (
     <View style={style} key={sectionID + rowID}></View>
   );
 }
});

var styles = StyleSheet.create({
  // Loading样式
  loadingContainer: {
    flex: 1,
    marginTop: 25,
    backgroundColor: "cyan",
    justifyContent: "center",
    alignItems: "center",
  },
  loadingText: {
    fontSize: 30,
    fontWeight: "bold",
    textAlign: "center",
    marginLeft: 10,
    marginRight: 10
  },
  // ListView Row样式
  rowContainer: {
    flexDirection: "row",
    padding: 5,
    alignItems: "center",
    backgroundColor: "#F5FCFF"
  },
  thumbnail: {
    width: 53,
    height: 81,
    backgroundColor: "gray"
  },
  textContainer: {
    flex: 1,
    marginLeft: 10
  },
  title: {
    marginTop: 3,
    fontSize: 18,
    textAlign: "center"
  },
  year: {
    marginTop: 3,
    marginBottom: 3,
    textAlign: "center"
  },
  // List Header样式
  header: {
    height: 44,
    backgroundColor: "#F5FCFF"
  },
  header_text: {
    flex: 1,
    fontSize: 20,
    fontWeight: "bold",
    textAlign: "center"
  },
  headerSeparator: {
    height: 1,
    backgroundColor: "#CCC"
  },
  listView: {
    marginTop: 25,
    backgroundColor: "#F5FCFF"
  }
});

module.exports = MovieList;

运行结果

运行结果.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容

  • 本文详细介绍了 XMLHttpRequest 相关知识,涉及内容: AJAX、XMLHTTP、XMLHttpReq...
    semlinker阅读 13,606评论 2 18
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,596评论 18 139
  • AFHTTPRequestOperationManager 网络传输协议UDP、TCP、Http、Socket、X...
    Carden阅读 4,319评论 0 12
  • 暮色浓 夜未央 一弯相思挂穹苍 两行清泪素颜霜 秋风起 叶彷徨 片片干红情如火 朵朵银黄诉衷肠 曲悠扬 路绵长 茕...
    默默Mona阅读 334评论 3 0
  • 连载:九境成丹万骨枯 《目录》[https://www.jianshu.com/p/4986656b28ca] 上...
    冬知饺子阅读 430评论 1 6