美文网首页
React Native Fetch 问题

React Native Fetch 问题

作者: 马六甲的笔记 | 来源:发表于2021-11-01 17:58 被阅读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 的几点说明

    • 查看 iOS源码Android 源码,可以看出在原生端 RN 并未支持 FormData 添加 Blob 类型数据。
    • RN 给了另外一种上传文件的方式,通过 {uri, ...} 指定文件地址,uri 支持 file://, content://(Android), 甚至还支持 http:// 网络图片
    • 如果必须要求 FormData 支持 Blob 对象,有两种拓展思路(需自行实现)
      • 先将 Blob 对象保存为临时文件,然后通过 {uri, ...} 添加,待请求完成后删除临时文件,这种方式会产生临时文件,且本来 Blob 对象已在内存中,保存为文件,发送请求,原生端会再次读取临时文件到内存中,有点浪费。
      • Request body 支持 Blob 对象,可根据 规则 自行将 formData 转换为 multipart/form-data 类型的 Blob 数据,如果 formData 中包含 {uri, ...} 类型文件,则需要将该类型转为 Blob 对象才能与 formData 中的其他 StringBlob 对象整合为一个统一的 Blob 对象,实现起来略微麻烦点。
      • 所以,如果可以调整思路避开使用 FormData Blob,就尽量避开吧

    ArrayBuffer / ArrayBufferView

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

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

    相关文章

      网友评论

          本文标题:React Native Fetch 问题

          本文链接:https://www.haomeiwen.com/subject/kadbaltx.html