react-native fetch的具体使用方法


Posted in Javascript onNovember 01, 2017

在前端快速发展地过程中,为了契合更好的设计模式,产生了 fetch 框架,此文将简要介绍下 fetch 的基本使用。

在 AJAX 时代,进行请求 API 等网络请求都是通过 XMLHttpRequest 或者封装后的框架进行网络请求。

现在产生的 fetch 框架简直就是为了提供更加强大、高效的网络请求而生,虽然在目前会有一点浏览器兼容的问题,但是当我们进行 Hybrid App 开发的时候,如我之前介绍的Ionic 和React Native,都可以使用 fetch 进行完美的网络请求。

fetch 初体验

在 Chrome 浏览器中已经全局支持了 fetch 函数,打开调试工具,在 Console 中可以进行初体验。先不考虑跨域请求的使用方法,我们先请求同域的资源,如在我的博客页面中,打开 Console 进行如下请求。

fetch("http://blog.parryqiu.com").then(function(response){console.log(response)})

返回的数据:

react-native fetch的具体使用方法

这样就很快速地完成了一次网络请求,我们发现返回的数据也比之前的 XMLHttpRequest 丰富、易用的多。

关于 fetch 标准概览

虽然 fetch 还不是作为一个稳定的标准发布,但是在其一直迭代更新的 标准描述 中,我们发现已经包含了很多的好东西。

fetch 支持了大部分常用的 HTTP 的请求以及和 HTTP 标准的兼容,如 HTTP Method,HTTP Headers,Request,Response。

fetch 的使用

fetch的入口函数定义在node_modules/whatwg-fetch.js文件中,如下

self.fetch = function (input, init) {
  return new Promise(function (resolve, reject) {
   var request = new Request(input, init)
   var xhr = new XMLHttpRequest()
   xhr.onload = function () {
    var options = {
     status: xhr.status,
     statusText: xhr.statusText,
     headers: parseHeaders(xhr.getAllResponseHeaders() || '')
    }
    options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')
    var body = 'response' in xhr ? xhr.response : xhr.responseText
    resolve(new Response(body, options))
   }
   xhr.onerror = function () {
    reject(new TypeError('Network request failed'))
   }
   xhr.ontimeout = function () {
    reject(new TypeError('Network request failed888888888888'))
   }
   xhr.open(request.method, request.url, true)
   if (request.credentials === 'include') {
    xhr.withCredentials = true
   }
   if ('responseType' in xhr && support.blob) {
    xhr.responseType = 'blob'
   }
   request.headers.forEach(function (value, name) {
    xhr.setRequestHeader(name, value)
   })
   xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
  })
 }

该函数在Network/fetch.js中被导出,最终在initializeCore.js中被注册为global的属性变为全局函数。fetch返回的是一个Promise。

跟随方法走向,依次调用的是XMLHttpRequest.js的send -> RCTNetworking.ios.js的sendRequest -> 最终调到原生端RCTNetworking.mm的sendRequest方法。

相关问题点:

1、为何fetch函数无法设置timeout?

为了设置fetch的timeout,我会如下定义一个函数

_timeout_fetch(fetch_promise, timeout = 15000) {
  let timeout_promise = new Promise(function (resolve, reject) {
   setTimeout(() => {
    reject('timeout promise');
   }, timeout)
  });
  return Promise.race([
   fetch_promise,
   timeout_promise
  ]);
 }

然后如下调用

this._timeout_fetch(
    fetch(url, requestParams)
     .then(response => response.json())
     .then(responseData => {
      resolve(responseData);
     })
     .catch(error => {
      reject(error);
     })
   )

先定义一个Promise,其在超时时间结束后reject。将这个Promise和fetch合并到Promise.race中,则一旦这两个请求谁先执行,另外一个会被舍弃。这样完成超时时间的设置。

但是查看源码发现oc中是有超时时间设置这个选项的,且js和oc通信时也传了这个参数,问题是出在入口函数fetch处,只需要在上面fetch方法中添加上如下

xhr.timeout = init.timeout || 0;

就可以在请求参数中设置超时时间了,如

let requestParams = {
   method: method,
   header: {
    "Content-Type": "application/json;charset=UTF-8",
   },
   timeout: 1000
  };

2、fetch函数为何无法cancel?

fetch在原生端是NSURLSessionDataTask发的请求,这个是可取消的。在js端的XMLHttpRequest.js中也发现了abort方法,调用能够取消当前网络请求。问题出在了fetch的接口函数。

首先,要想请求能够取消,得拿到当前请求对应的requestId。请求的执行顺序是js端发起 -> OC生成Request,得到requestId,利用NSURLSessionDataTask发起请求 -> 将requestId通过回调的形式传回给js端,js若想取消该请求,执行abort方法即可。

要想fetch函数能够执行cancel,只需该方法将XMLHttpRequest对象返回即可。但是那样,就不再是一个Promise了。
也可以将cancel方法绑定到返回的Promise对象上,修改方法如下

self.fetch = function (input, init) {
  var xhr = new XMLHttpRequest()
  let p = new Promise(function (resolve, reject) {
   var request = new Request(input, init)
   // xhr的各种设置,回调等
  })
  p.cancel = () => {
   xhr.abort()
  }
  return p;
 }

如此,调用的时候就比较恶习了,要如下

let promise = fetch(url);
  promise.then(res => {
  }).then(res => {
  }).catch(err => {
  })
  promise.cancel() // 取消该网络请求

不能fecth().then().then()的模式调用,因为这样会导致返回的那个Promise不再是上面绑定了cancel的那个Promise。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js或css实现滚动广告的几种方案
Jan 28 Javascript
html+javascript实现可拖动可提交的弹出层对话框效果
Aug 05 Javascript
JavaScript 实现完美兼容多浏览器的复制功能代码
Apr 28 Javascript
原生JavaScript实现动态省市县三级联动下拉框菜单实例代码
Feb 03 Javascript
javascript实现移动端上的触屏拖拽功能
Mar 04 Javascript
详解react-router4 异步加载路由两种方法
Sep 12 Javascript
浅析Node.js非对称加密方法
Jan 29 Javascript
详解Vue微信授权登录前后端分离较为优雅的解决方案
Jun 29 Javascript
学习jQuery中的noConflict()用法
Sep 28 jQuery
基于React Native 0.52实现轮播图效果
Aug 25 Javascript
vue-cli+axios实现文件上传下载功能(下载接收后台返回文件流)
May 10 Javascript
详解Webpack4多页应用打包方案
Jul 16 Javascript
Vue异步加载about组件
Oct 31 #Javascript
微信小程序顶部可滚动导航效果
Oct 31 #Javascript
React Native使用Modal自定义分享界面的示例代码
Oct 31 #Javascript
Bootstrap3.3.7导航栏下拉菜单鼠标滑过展开效果
Oct 31 #Javascript
使用nvm管理不同版本的node与npm的方法
Oct 31 #Javascript
javascript高级模块化require.js的具体使用方法
Oct 31 #Javascript
JS简单实现点击跳转登陆邮箱功能的方法
Oct 31 #Javascript
You might like
56.com视频采集接口程序(PHP)
2007/09/22 PHP
纯真IP数据库的应用 IP地址转化成十进制
2009/06/14 PHP
PHP中防止SQL注入攻击和XSS攻击的两个简单方法
2010/04/15 PHP
php中计算中文字符串长度、截取中文字符串的函数代码
2011/08/09 PHP
phpstorm 正则匹配删除空行、注释行(替换注释行为空行)
2018/01/21 PHP
laravel高级的Join语法详解以及使用Join多个条件
2019/10/16 PHP
jquery 插件学习(五)
2012/08/06 Javascript
js关于字符长度限制的问题示例探讨
2014/01/24 Javascript
javascript 自定义回调函数示例代码
2014/09/26 Javascript
AngularJs根据访问的页面动态加载Controller的解决方案
2015/02/04 Javascript
javascript实现简单的省市区三级联动
2015/05/14 Javascript
微信小程序左右滑动切换页面详解及实例代码
2017/02/28 Javascript
js+html5实现半透明遮罩层弹框效果
2020/08/24 Javascript
vue单页开发父子组件传值思路详解
2018/05/18 Javascript
vue-cli3 配置开发与测试环境详解
2019/05/17 Javascript
详解nuxt 微信公众号支付遇到的问题与解决
2019/08/26 Javascript
原生JS实现汇率转换功能代码实例
2020/05/13 Javascript
Javascript执行上下文顺序的深入讲解
2020/11/04 Javascript
Vue用mixin合并重复代码的实现
2020/11/27 Vue.js
Python基于贪心算法解决背包问题示例
2017/11/27 Python
python使用筛选法计算小于给定数字的所有素数
2018/03/19 Python
python使用Matplotlib画条形图
2020/03/25 Python
使用python爬取抖音视频列表信息
2019/07/15 Python
如何使用django的MTV开发模式返回一个网页
2019/07/22 Python
django项目简单调取百度翻译接口的方法
2019/08/06 Python
学习Django知识点分享
2019/09/11 Python
Python 剪绳子的多种思路实现(动态规划和贪心)
2020/02/24 Python
草莓网英国官网:Strawberrynet UK
2017/02/12 全球购物
The Hut美国/加拿大:英国领先的豪华在线百货商店
2019/03/26 全球购物
abstract 可以和 virtual 一起使用吗?可以和 override 一起使用吗?
2012/10/15 面试题
教育科研先进个人材料
2014/01/26 职场文书
《桥》教学反思
2014/04/09 职场文书
2015年青年教师工作总结
2015/05/25 职场文书
我的法兰西岁月观后感
2015/06/09 职场文书
基于Python实现流星雨效果的绘制
2022/03/18 Python
Python数据处理的三个实用技巧分享
2022/04/01 Python