React Native 中 fetch的使用心得

最近在搞React Native 开发中,发现fetch与以前浏览器中使用XMLHttpRequest有一些差别;
XMLHttpRequest方式的用法,相信大家已经很熟悉了,这里就不介绍了。

fetch的基本用法GET、POST

先来看看普通的GET的请求:

// fetch(url,options).then().catch()
// url (required),options (optional)
fetch('http://nero-zou.com/test',{
    method: 'GET'
}).then(function(response) {
    
}).catch(function(err) {
    // Error Handle
});

fetch会返回一个Promise对象,返回的数据会在response参数中;

请求头(Request Headers)

通过 new Headers(),你也可以自由地设置请求头:

// 创建一个空的Headers 实例
var headers = new Headers();

// 添加 headers
headers.append('Content-Type','text/plain');
headers.append('X-My-Custom-Header','CustomValue');

// 检测、获取、设置 header
headers.has('Content-Type'); // true
headers.get('Content-Type'); // "text/plain"
headers.set('Content-Type','application/json');

// 删除一个 header
headers.delete('X-My-Custom-Header');

// 创建时带上参数
var headers = new Headers({
    'Content-Type': 'text/plain','X-My-Custom-Header': 'CustomValue'
});

你可以使用append,has,get,set,和delete修改request headers. Headers与Request的组合是这样的:

var request = new Request('http://ner-zou.com/test',{
    headers: new Headers({
        'Content-Type': 'text/plain'
    })
});

fetch(request).then(function() { /* handle response */ });

响应(Response)

fetch返回的 then方法一个response参数,它是一个Response实例。
Response有如下方法:

  • clone() - 复制一份response

  • error() - 返回一个与网络相关的错误

  • redirect() - 返回了一个可以重定向至某URL的response.

  • arrayBuffer() - 返回一个带有ArrayBuffer的Promise.

  • blob() - 返回一个带有Blob的Promise.

  • formData() - 返回一个带有FormData的Promise.

  • json() - 返回一个带有JSON格式对象的Promise.

  • text() - 返回一个带有文本的Promise.

下面看看fetch如何接受服务器端返回的JSON数据:

fetch('http://nero-zou.com/test.json').then(function(response) { 
    return response.json();// 转换为JSON
}).then(function(data) {
    console.log(data); // data 就是一个JavaScript object
});

加上一些错误处理:

fetch('http://nero-zou.com/test.json')
    .then((response) => {
        if (response.ok) {
            return response.json()
        } else {
            console.error('服务器繁忙,请稍后再试;\r\nCode:' + response.status)
        }
    })
    .then((data) => {
        console.log(data)
    })
    .catch((err)=> {
        console.error(err)
    })

response.ok会将404、500等这些请求错误给过滤掉;

GET请求带上参数

官方推荐了一种写法:

var url = new URL("https://geo.example.org/api"),params = {lat:35.696233,long:139.570431}
Object.keys(params).forEach(key => url.searchParams.append(key,params[key]))
fetch(url).then(/* … */)

但是URL这个方法,在React Native 中并没有实现,那么就只能我们自己来拼接url了,
这里我们对 GET请求封装一个方法

/**
 * 基于 fetch 封装的 GET请求
 * @param url
 * @returns {Promise}
 */
export function R_GET(url,params) {
    if (params) {
        let paramsArray = []
        Object.keys(params).forEach(key => paramsArray.push(key + '=' + encodeURIComponent(params[key])))
        if (url.search(/\?/) === -1) {
            url += '?' + paramsArray.join('&')
        } else {
            url += '&' + paramsArray.join('&')
        }
    }
    return new Promise(function (resolve,reject) {
        fetch(url)
            .then((response) => {
                if (response.ok) {
                    return response.json()
                } else {
                    reject('服务器繁忙,请稍后再试;\r\nCode:' + response.status)
                }
            })
            .then((response) => {
                if (response && response.error_code === 0) {
                    resolve(response)//response.error_code 是与服务器端的约定,非0就是错误
                } else {
                    reject(response.message)//response.message也是与服务器端的约定,error_code !==0 就需要返回message
                }
            })
            .catch((err)=> {
                reject(_parseErrorMsg(err))
            })
    })
}

在服务器端(Express.js)中可以这么接收参数

//假如在客户端这么请求的话
//R_GET('http://nero-zou.com/test',{name:nero})
//等同于这样 fetch('/test?name=nero')


//... 
router.get('/test',function (req,res) {
    res.send({
        error_code: 0,data: {name: req.query.name},//这里的req.query.name 就是nero了
        message: 'success'
    });
});

POST数据给服务器

客户端可以这么写:

fetch('http://nero-zou.com/test',{
    method: 'post',headers: {
        'Accept': 'application/json','Content-Type': 'application/json' //记得加上这行,不然bodyParser.json() 会识别不了
    },body: JSON.stringify({
        name: "nero",email: "Nero@Nero-zou.com"
    })
});

在服务器端(Express.js)中可以这么接收数据

//...
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
//...

//... 省略其他无关代码
router.post('/test',data: req.body,//把发过来的数据原封不动返回回去,这里只是举例
        message: 'success'
    });
});

一些参考文章

相关文章

react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接...
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc ...