React Native Fetch 问题

2021-11-01  本文已影响0人  马六甲的笔记

Fetch Request

web 环境下 Request Body 支持的 参数 类型有: String, URLSearchParams, Blob/File, FormData, ArrayBuffer, ArrayBufferView

不同之处
① RN 自身本仅支持 XMLHttpRequest 进行网络请求,支持的 Request Body 可通过 源码1 > 源码2 > 源码3 查看,缺少了对 URLSearchParams 的支持。
② RN Fetch 使用 whatwg-fetch,通过 XMLHttpRequest 实现了 Fetch 功能,根据 源码1源码2 可以看出 whatwg-fetch 支持 URLSearchParams 类型的 Request Body ,但在 RN 中少了临门一脚。

String

body 为 String,请求格式如下

fetch
content-type: text/plain;charset=UTF-8
---------------------------
string

URLSearchParams

body 为 URLSearchParams,请求格式如下

fetch
content-type: application/x-www-form-urlencoded;charset=UTF-8
---------------------------
String(URLSearchParams): foo=foo&bar=bar

不同之处:根据 web 示例,支持 new URLSearchParams("foo=foo&bar=bar"),但根据 RN 源码,仅支持 new URLSearchParams({foo:"foo", bar:"bar"}) 形式,且没有实现 get、has、set 等方法。

Blob/File

body 为 Blob,请求格式如下

fetch
content-type: Blob.type
---------------------------
String(Blob)

不同之处:根据 Blob 文档RN 源码
① 可以看到 RN Blob 未实现 arrayBufferstreamtext 方法。
② 创建 Blob 对象 new Blob(array, options) 中的 array 参数,RN 只能使用 StringBlob,而不能使用 ArrayBufferArrayBufferView

关于 RN Blob (File 是继承 Blob 实现的,二者基本一致,不再累述):

在浏览器中,Blob 对象的数据缓存在浏览器中并与变量指针绑定。在 RN 中,Blob 对象的数据将缓存在原生端(其实也就是 app 运行内存中),并生成一个唯一的 id,返回给 js 端,也就是说在 js 端存储的仅是一个 id。后续则可通过 FileReader 与原生端交互,读取 Blob 对象的实际数据。Fetch 函数内部已实现了数据读取,可将 Blob 直接设置为 Request Body

Blob 的创建方式:

① 通过函数,比如 Fetch / XMLHttpRequest 请求可以获取到 Response Blob,网络请求是在原生端完成的,完成后原生端缓存响应结果,返回唯一 id 给 js 端创建 Blob。

② 也可以使用如下方法直接创建,js 会先将创建数据传递给原生端缓存,然后使用原生端返回的唯一 id 创建 Blob

const body = new Blob(
   ['<a id="a"><b id="b">hey!</b></a>'], 
   {type : 'text/html', lastModified:Date.now()}
);

-> 创建 -> string 传到原生端 -> 返回 id -> js{id:....,type,}

const stream = new Blob(
   [body, 'string'], 
   {type : 'text/html', lastModified:Date.now()}
);

-> 传递参数 body 的 id 和 string -> 返回新 id -> js{id:...,type,}

FormData

body 为 Blob,请求格式如下 (以上 body 格式的 header content-typewhatwg-fetch 实现,以下 header content-type 则在原生的 Android 端iOS 端 实现 )

fetch
content-type: multipart/form-data; boundary=...
---------------------------
String(FormData)

不同之处:根据 FormData 文档RN 源码,可以看到有以下不同
① RN 仅实现了 appendgetParts 方法,而没有实现 gethasset 等方法。如果在 RN 中需要对已添加的 form data 进行修改,可通过 FormData._parts 进行操作,但这种方法并不安全,后续 RN 可能会对 _parts 更新,造成兼容性问题。
append 方法与浏览器端的实现不同

// 浏览器, value 支持 String / File / Blob
var formData = new FormData();
formData.append('username', 'Chris');
formData.append('userpic', myFileInput.files[0], 'chris.jpg');
formData.append('blob', new Blob(
   ['<a id="a"><b id="b">hey!</b></a>'], 
   {type : 'text/html', lastModified:Date.now()}
));

// RN, value 支持 String / FIle
var formData = new FormData();
formData.append('username', 'Chris');
formData.append('userpic', {
    uri: String,
    type: 'image/jpeg',
    name: 'photo.jpg',
});

关于 RN FormData 的几点说明

ArrayBuffer / ArrayBufferView

fetch
content-type: ......
---------------------------
String(ArrayBuffer)

ArrayBuffer 将作为 Request body 发送,与 Blob/File 相似,不同之处在于:在发送请求时,必须要在 Request.Headers 中指定 content-type,否则会请求失败。(而 Blob/File Body 则无需,在未指定的情况下会使用 application/octet-stream 作为 content-type 默认值)

上一篇 下一篇

猜你喜欢

热点阅读