$ ls ~yifei/notes/

浏览器用于替换 ajax/xhr 的 fetch api

Posted on:

Last modified:

fetch 是近年来浏览器实现的一个用于取代 xhr 的 API,相比于 xhr 来说更加简单易用安全且强大。 主要区别有:

  • fetch 基于 promise,可以使用 await 直接调用;
  • fetch 对于 400 和 500 错误依然会正常返回而不会报错。只有在网络错误的时候才会抛出异常;
  • fetch 默认只会携带同一个域名下的 cookies,也就是 same-origin,默认更安全;
  • fetch 不接受跨域的 Set-Cookie。

基本用法

const response = await fetch("http://example.com/movies.json");
const myJson = await response.json(); // text() 返回纯文本
console.log(JSON.stringify(myJson));
  • response.ok 是否请求返回了 2XX 代码
  • response.status 返回的状态码,比如 200, 404 等
  • await response.blob() 返回二进制文件
  • await response.text() 返回文本文件
  • await response.json() 返回解析的 json

增加选项

特别注意的是,在 Flask 等后端框架中,如果不添加 application/json 的 header, 默认不会 解析 json, 太坑了。默认情况下 fetch 是会携带同一个域名下的 Cookie 的

try {
  // Default options are marked with *
  const response = await fetch(url, {
    method: "POST", // *GET, POST, PUT, DELETE, etc.
    mode: "cors", // no-cors, *cors, same-origin
    cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
    credentials: "same-origin", // include, *same-origin, omit
    headers: {
      "Content-Type": "application/json"
      // "Content-Type": "application/x-www-form-urlencoded",
    },
    redirect: "follow", // manual, *follow, error
    referrer: "no-referrer", // no-referrer, *client
    body: JSON.stringify(data) // body data type must match "Content-Type" header
  });
  console.log(await response.json());
} catch (error) {
  console.error(error);
}

添加 URL 参数

// 注意这个其实挺坑的,必须是一个完整的 url,而不能使用一个片段
let url = new URL('https://sl.se')

let params = {lat:35.696233, long:139.570431} // or:
let params = [['lat', '35.696233'], ['long', '139.570431']]

url.search = new URLSearchParams(params).toString();

fetch(url)

在 Node 中可能需要:import {URL, URLSearchParams} from 'url'

携带 cookies

fetch 的 credentials 有三个选项:

  • omit 不携带任何 cookies
  • include 携带所有 cookies
  • same-origin 只有向当前网站的同源域名发送请求时才携带 cookies

其中 same-origin 是默认选项。

使用自定义 headers 和 request

const headers = new Headers();
headers.append("Content-Type", "text/plain");
headers.append("Content-Length", content.length.toString());
headers.append("X-Custom-Header", "ProcessThisImmediately");

// 另一种方法是直接使用字典
const headers = new Headers({
  "Content-Type": "text/plain",
})

const init = {
  method: "POST",
  headers: headers,
  mode: "cors",
  cache: "default",
}

const request = new Request("flowers.jpg", init);
const rsp = await fetch(request);

参考

  1. https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
  2. https://stackoverflow.com/questions/34558264/fetch-api-with-cookie
  3. https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials
WeChat Qr Code

© 2016-2022 Yifei Kong. Powered by ynotes

All contents are under the CC-BY-NC-SA license, if not otherwise specified.

Opinions expressed here are solely my own and do not express the views or opinions of my employer.

友情链接: MySQL 教程站