欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

react-native fetch的具体使用方法

程序员文章站 2022-04-09 21:19:45
在前端快速发展地过程中,为了契合更好的设计模式,产生了 fetch 框架,此文将简要介绍下 fetch 的基本使用。 在 ajax 时代,进行请求 api 等网络请求都是...

在前端快速发展地过程中,为了契合更好的设计模式,产生了 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。

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