post reactnative 请求

2017-08-30 23:55:27 LJFPHP 阅读数 880

最近做React native开发,遇到了这种fetch请求,说实话,以前用ajax比较多,对这种fetch请求

还真是不怎么了解,所以花时间百度一下,看看大家怎么用的。顺便也需要封装一下网路请求的

get和post方法,方便下面的调用。

话不多说,直入主题:

开发中,从网络上加载数据一直是重点和难点,尤其是在做相应的细节优化方面,在React Native 中通常是用哪种

方式加载网络数据呢? 

React Native 中通常是通过 Ajax 从服务器获取数据,在 componentDidMount 方法中创建 Ajex 请求,等到请求成功,

再用 this.setState 方法重新渲染UI

一、什么是 fetch


  • fetch 目前还不是 W3C 规范,是由 whatag 负责研发。与 Ajax 不同的是,它的 API 不是事件机制,而是采用目前

  • 流行的 Promise(MDN Promise) 方式处理

  • 格式:

    fetch(url, init)
    .then((response) => {   // 数据解析方式
    })
    .then((responseData) => {       // 获取到的数据处理
    })
    .catch((error) => { // 错误处理
    })
    .done();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 上面的示例中的 init 是一个对象,他里面包含了: 
    • method:请求方式(GET、POST、PUT等)。
    • headers:需要用到 Headers 对象使用这个参数。
    • body:需要发送的数据
    • mode:跨域设置(cors, no-cors, same-origin)
    • cache:缓存选项(default, no-store, reload, no-cache, force-cache, or only-if-cached)

译注:

  • body:不可传对象,用JSON.stringify({…})也不可以,在jQuery 中会自动将对象封装成 formData 形式,fetch不会。
  • mode属性控制师傅跨域,其中 same-origin(同源请求,跨域会报error)、no-cors(默认,可以请求其它域的资源,
  • 不能访问response内的属性)和 cros(允许跨域,可以获取第三方数据,必要条件是访问的服务允许跨域访问)。
  • 使用 fetch 需要注意浏览器版本,但 React-Native 则不需要考虑。
  • response 对象可以有如下几种解析方式

    • arrayBuffer()
    • json()
    • text()
    • blob()
    • formData()
  • 下面是一个最基本的请求,只传入一个参数,默认为 GET 方式请求


    fetch(url)
    .then((response) => response.json())        // json方式解析,如果是text就是 response.text()
    .then((responseData) => {   // 获取到的数据处理
    })
    .catch((error) => {     // 错误处理 
    })
    .done();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 针对表单提交的请求,我们通常采用 POST 的方式。

方式一:


    fetch(url, {
        method: "POST",
        headers: {
            "Content-Type": "application/x-www-form-urlencoded"
        }
        body:"key1=value&key2=value…&keyN=value"
    })
    .then((response) => {       // 数据解析方式
    })
    .then((responseData) => {       // 获取到的数据处理
    })
    .catch((error) => { // 错误处理
    })
    .done();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 在 JQuery 中,传入对象框架会自动封装成 formData 的形式,但是在 fetch 中没有这个功能,所以我们需要
  • 自己初始化一个 FormData直接传给 body (补充:FormData也可以传递字节流实现上传图片功能)

方式二:

    let formData = new FormData();
    formData.append("参数", "值");
    formData.append("参数", "值");

    fetch(url, {
        method:'POST,
        headers:{},
        body:formData,
        }).then((response)=>{
            if (response.ok) {
                return response.json();
            }
        }).then((json)=>{
            alert(JSON.stringify(json));
        }).catch.((error)=>{
            console.error(error);
        })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

译注:

  • application/x-www-form-urlencoded: 窗体数据被编码为名称/值对。这是标准的编码格式。
  • multipart/form-data: 窗体数据被编码为一条消息,页上的每个控件对应消息中的一个部分。
  • text/plain: 窗体数据以纯文本形式进行编码,其中不含任何控件或格式字符。
  • Fetch 跨域请求的时候默认是不带 cookie 的,如果需要进行设置 credentials:’include’。

二、获取 HTTP 头信息


    console.log(response.headers.get('Content-Type'));
                        ...
    console.log(response.headers.get('Date'));
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
注意:使用fetch请求,如果服务器返回的中文出现了乱码,则可以在服务器端设置如下代码解决: 
produces="text/html;charset=UTF-8"

三、fetchRequest使用如下:

GET方法:
get(url, func=false) {
  return fetch(url) // GET方式 获取Json数据  
    .then((response) => {
      let data = response.json(); // 解析数据为 json格式
      return data; // 传递数据给下一步
    })
    .then((json_data) => { // 接收刚刚获取到的数据  
      // 如果有回调
      if( false!==func ){
        func(json_data);
      }
    })
    .catch ((error) => { // fetch开始,到最后一个then,有错误出现,则会捕捉错误。
      console.warn('Catch info');
      console.error(error);
    });
},
如图所示:url为我们请求的url
封装的步骤就是按照官方给出的步骤,一步步走下去
POST请求:
 post(url, ini_json={}, unlisted=false) {
    let token = '',   // 身份识别码
        headers = {   // http请求头
          'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
        },
        body = '',    // 用于post的数据  
        func = undefined !== ini_json.func? ini_json.func : false; // 回调函数

    // 请求时,请求地址带上token 
    if( false=== unlisted ){
      token = unlisted;// 这里是token
    }
    if( undefined !== ini_json.headers ){
      headers = init_json.headers;
    }
    // 暂不支持数组传输,已建议同类数据以逗号分隔
    if( undefined !== ini_json.data ){
      // 如果有数据
      for(let i in ini_json.data){
        body  +=  i + '=' + encodeURIComponent(ini_json.data[i]) + '&';
      }
    }
    return fetch(url, {
      method: 'POST', 
      headers:  headers, 
      body: body,
    })
    .then((response) => {
      let data = response.json(); // 解析数据为 json格式
      return data; // 传递数据给下一步
    })
    .then((json_data) => { // 接收刚刚获取到的数据  
      // 如果有回调
      if( false!==func ){
        func(json_data);
      }
    })
    .catch ((error) => { // fetch开始,到最后一个then,有错误出现,则会捕捉错误。
      console.warn('Catch info');
      console.error(error);
    });
  }
}
如图所示:这个post请求加了一些业务上的逻辑。包括请求时带上token等
步骤也是按照官方的步骤,先请求--》获取数据--》回调处理--》捕获错误信息

参考链接:http://blog.csdn.net/withings/article/details/71331726
https://segmentfault.com/a/1190000006099651
end

2019-05-12 20:28:41 qq_36699930 阅读数 566

很多移动应用都需要从远程地址中获取数据或资源。你可能需要给某个REST API发起POST请求以提交用户数据,又或者可能仅仅需要从某个服务器上获取一些静态内容 - 以下就是你会用到的东西。

使用Fetch

React Native提供了和web标准一致的Fetch API,如果你之前使用过XMLHttpRequest(即俗称的ajax)或是其他的网络API,那么Fetch用起来将会相当容易上手。这篇文档只会列出Fetch的基本用法,并不会讲述太多细节,你可以使用你喜欢的搜索引擎去搜索fetch api关键字以了解更多信息。

发起请求

要从任意地址获取内容的话,只需简单地将网址作为参数传递给fetch方法即可(fetch这个词本身也就是获取的意思):

fetch('https://facebook.github.io/react-native/movies.json')

获取还有可选的第二个参数,可以用来定制HTTP请求一些参数。你可以指定标头参数,或是指定使用POST方法,又或是提交数据等等:

fetch('https://mywebsite.com/endpoint/', {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    firstParam: 'yourValue',
    secondParam: 'yourOtherValue',
  }),
});

提交数据的格式关键取决于headers中的Content-Type。Content-Type有很多种,对应体的格式也有区别。到底应该采用什么样的Content-Type取决于服务器端,所以请和服务器端的开发人员沟通确定清楚。常用的’Content-Type ‘除了上面的’应用程序/ JSON’,还有传统的网页表单形式,示例如下:

fetch('https://mywebsite.com/endpoint/', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  body: 'key1=value1&key2=value2',
});

注意:使用Chrome调试目前无法观测到React Native中的网络请求,你可以使用第三方的react-native-debugger来进行观测。

处理服务器的响应数据

上面的例子演示了如何发起请求。很多情况下,你还需要处理服务器回复的数据。

网络请求天然是一种异步操作(译注:同样的还有asyncstorage,请不要再问怎样把异步变成同步!无论在语法层面怎么折腾,它们的异步本质是无法变更的。异步的意思是你应该趁这个时间去做点别的事情,比如显示loading,而不是让界面卡住傻等).Fetch方法会返回一个Promise,这种模式可以简化异步风格的代码(译注:同样的,如果你不了解承诺,建议使用搜索引擎补课):

function getMoviesFromApiAsync() {
  return fetch('https://facebook.github.io/react-native/movies.json')
    .then((response) => response.json())
    .then((responseJson) => {
      return responseJson.movies;
    })
    .catch((error) => {
      console.error(error);
    });
}

你也可以在React Native应用中使用ES2017标准中的async/ await语法:

// 注意这个方法前面有async关键字
async function getMoviesFromApi() {
  try {
    // 注意这里的await语句,其所在的函数必须有async关键字声明
    let response = await fetch(
      'https://facebook.github.io/react-native/movies.json',
    );
    let responseJson = await response.json();
    return responseJson.movies;
  } catch (error) {
    console.error(error);
  }
}

别忘了赶住fetch可能抛出的异常,否则出错时你可能看不到任何提示。

import React from 'react';
import { FlatList, ActivityIndicator, Text, View  } from 'react-native';

export default class FetchExample extends React.Component {

  constructor(props){
    super(props);
    this.state ={ isLoading: true}
  }

  componentDidMount(){
    return fetch('https://facebook.github.io/react-native/movies.json')
      .then((response) => response.json())
      .then((responseJson) => {

        this.setState({
          isLoading: false,
          dataSource: responseJson.movies,
        }, function(){

        });

      })
      .catch((error) =>{
        console.error(error);
      });
  }



  render(){

    if(this.state.isLoading){
      return(
        <View style={{flex: 1, padding: 20}}>
          <ActivityIndicator/>
        </View>
      )
    }

    return(
      <View style={{flex: 1, paddingTop:20}}>
        <FlatList
          data={this.state.dataSource}
          renderItem={({item}) => <Text>{item.title}, {item.releaseYear}</Text>}
          keyExtractor={(item, index) => item.id}
        />
      </View>
    );
  }
}

默认情况下,iOS 会阻止所有 http 的请求,以督促开发者使用 https。如果你仍然需要使用 http 协议,那么首先需要添加一个 App Transport Security 的例外,详细可参考这篇帖子。
https://segmentfault.com/a/1190000002933776

从 Android9 开始,也会默认阻止 http 请求,请参考相关配置
https://blog.csdn.net/qq_40347548/article/details/86766932

使用其他的网络库

React Native 中已经内置了XMLHttpRequest API(也就是俗称的 ajax)。一些基于 XMLHttpRequest 封装的第三方库也可以使用,例如frisbee或是axios等。但注意不能使用 jQuery,因为 jQuery 中还使用了很多浏览器中才有而 RN 中没有的东西(所以也不是所有 web 中的 ajax 库都可以直接使用)。

var request = new XMLHttpRequest();
request.onreadystatechange = (e) => {
  if (request.readyState !== 4) {
    return;
  }

  if (request.status === 200) {
    console.log('success', request.responseText);
  } else {
    console.warn('error');
  }
};

request.open('GET', 'https://mywebsite.com/endpoint/');
request.send();

WebSocket 支持

React Native 还支持WebSocket,这种协议可以在单个 TCP 连接上提供全双工的通信信道。

var ws = new WebSocket('ws://host.com/path');

ws.onopen = () => {
  // connection opened
  ws.send('something'); // send a message
};

ws.onmessage = (e) => {
  // a message was received
  console.log(e.data);
};

ws.onerror = (e) => {
  // an error occurred
  console.log(e.message);
};

ws.onclose = (e) => {
  // connection closed
  console.log(e.code, e.reason);
};
2019-04-22 10:50:47 winux123 阅读数 883

react native 端参考代码:

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


//Post方法, 需要请求体body
/*
* FromData
* 主要用于序列化表单以及创建与表单格式相同的数据
*
* var data = new FormData();
* data.append("name","hello");
* append方法接收两个参数,键和值(key,value),分别表示表单字段的名字 和 字段的值,可添加多个
*
* 在jQuery中,"key1=value1&key2=valu2" 作为参数传入对象框架,会自动分装成FormData形式
* 在Fetch 中,进行post进行post请求,需要自动创建FormData对象传给body
*
* */
function postRequest(url) {
    //将"key1=value1&key2=valu2" 形式封装整FromData形式
    let formData = new FormData();
    formData.append("id","15");
    formData.append("verName","1111aaaa");

    var opts = {
        method:"POST",   //请求方法
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
        },
        body:formData,   //请求体
    };


   fetch(url , {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
        },
        body: formData,
    }).then((response) => {
        if (response.ok) {
            return response.json();
        }
    }).then((json) => {
        console.log(json);
        console.log(json.id);
       console.log(json.verName);
        alert(JSON.stringify(json));
    }).catch((error) => {
        console.error(error);
    })
}


export default class HomeScreen extends Component {
    render() {
        return(
            <View style={styles.container}>
                {/*注意: 方法调用方式,绑定了this */}
                <TouchableOpacity onPress={postRequest.bind(this,"http://jmbsjk.com/test/test2.php")}>
                    <View style={styles.btn}>
                        <Text>Post</Text>
                    </View>
                </TouchableOpacity>
            </View>
        );
    }
}

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

 

PHP服务器端代码:

<?php

   // $json = file_get_contents("php://input");
   // $data = json_decode($json, true);
    //$id=$data['id'];
    
    $id=$_POST['id'];
    $verName=$_POST['verName'];
    
    //链接数据库
    $con = mysqli_connect("localhost","my_db","123456",'my_db',3306);

    $result = mysqli_query($con,"select * from recordClear where recordId=".$id."");
    $num = mysqli_num_rows($result);
    //printf("总共返回 %d 行数据。",$num);
      // 释放结果集
    //mysqli_free_result($result);
    //获取星期
    $time2 = date("N",time());
    //printf("今天:%s",$time2);
    $sql = "INSERT INTO recordClear(recordId,recordCount,cleardate) VALUES(".$id.",'1',".$time2.")";
    $query = mysqli_query($con,$sql);
    mysqli_close($con);

    $resulttt = array(
    'id'=>$id,
    'verName'=>$verName,            
    );
    echo json_encode($resulttt,128);

?>

 

2019-02-21 15:30:03 weixin_42547619 阅读数 697

在react-native中调用接口有3中方法,这会儿说一下fetch 的post请求示例

  let formData = new FormData();
        formData.append("userName", this.state.userName);
        formData.append("password", this.state.password);
        formData.append("type", this.state.buttonType ? 1 : 2);
        let url = config.serverUrl + "/User/LoginOrRegister/login";
        let opts = {
            method: "POST",   //请求方法
            body: formData,   //请求体
        }
        fetch(url, opts)
            .then((response) => response.json())
            .then((responseData) => {
                // 注意,这里使用了this关键字,为了保证this在调用时仍然指向当前组件,我们需要对其进行“绑定”操作
                if (responseData.data) {
                    alert(JSON.stringify(responseData.data))
                } else {
                    alert(responseData.message)
                }
            });
2019-03-14 09:02:46 duoduo_11011 阅读数 480

React Native 提供了和 web 标准一致的Fetch API,用于满足开发者访问网络的需求。

Fetch 语法

使用 fetch 的构造函数请求数据后,返回一个 Promise 对象,然后根据具体的实际情况处理。

fetch("http://baidu.com")  
.then(function(response){  
   // ...
})

说明:
在请求后的 Response 中,常常有如下返回情况:

  • Response.status 也就是 StatusCode,如成功就是 200 ;
  • Response.statusText 是 StatusCode 的描述文本,如成功就是 OK ;
  • Response.ok 一个 Boolean 类型的值,判断是否正常返回,也就是 StatusCode 为 200-299 。

Fetch 请求方式

1. get方式

fetch('http://nero-zou.com/test', {  
    method: 'GET'
}).then(function(response) {
    //获取数据,数据处理
}).catch(function(err) {
    //错误处理
});

2. post方式

let param = {user:'xxx',phone:'xxxxxx'};
fetch(url, {  
    method: 'post',
    body: JSON.stringify(param)
}).then(function(response) {
    //获取数据,数据处理
});

对Fetch进行封装

(1)这里我们对 Fetch 进行一个封装,实现一个支持 POST 请求的简单 API。

//带参数的POST请求
function postRequest(url, data, callback) {
  var opts = {
    method: 'POST',
    headers: {
      'Accept': 'application/json'
    },
    body: JSON.stringify(data)
  }
 
  fetch(url, opts)
  .then((resonse) => resonse.text())
  .then((responseText) => {
    //将返回的JSON字符串转成JSON对象,并传递到回调方法中
    callback(JSON.parse(responseText));
  });
}

(2)使用样例

var data = {id:123, name:'hangge.com'};
postRequest('https://httpbin.org/post', data, function(result){
  alert("请求成功!");
  console.log(result);
})

实例

1.逻辑代码

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

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

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      movies: null,
    };
    this.fetchData = this.fetchData.bind(this);
  }

  componentDidMount() {
    this.fetchData();
  }

  fetchData() {
    fetch(REQUEST_URL)
      .then((response) => response.json())
      .then((responseData) => {
        this.setState({
          movies: responseData.movies,
        });
      });
  }

  render() {
    if(!this.state.movies) {
      return this.renderLoadingView();
    }
    var movie = this.state.movies[0];
    return this.renderMovie(movie);
  }

  renderLoadingView() {
    return (
      <View style = {styles.container}>
        <Text>loading...</Text>
      </View>
    );
  }

  renderMovie(movie) {
    return(
      <View style = {styles.container}>
        <Image 
          style = {styles.thumbnail}
          source = {{uri: movie.posters.thumbnail}}
        />

        <View style = {styles.rightContainer}>
          <Text style = {styles.title}>{movie.title}</Text>
          <Text style = {styles.year}>{movie.year}</Text>
        </View>

      </View>
    );
  }
  
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  thumbnail: {
    width: 100,
    height: 80
  },
  rightContainer: {
    flex: 1
  },
  title: {
    fontSize: 20,
    marginBottom: 8,
    textAlign: 'center'
  },
  year: {
    textAlign:'center'
  }
});

2. 效果图
fetch.jpg