将数据传递给 Axios 中的服务

Pass Data to Service in Axios

我想在我的 header 中设置 _boundry

首先,我发送表单数据:

//component.js

const form = new FormData();

form.append('email', 'eray@serviceUser.com')
form.append('password', '12121212')

dispatch(FetchLogin.action(form))

其次,我准备api调用;

//loginService.js

import api from '@/Services'

export default async form => {
  const response = await api.post('user/login/', form)
  return response.data
}

第三,我打api电话;

//Services/index.js

import axios from 'axios'
import { Config } from '@/Config'

const instance =  axios.create({
  baseURL: Config.API_URL,
  headers: {
    'Content-Type': `multipart/form-data; boundary=${form._boundary}`, //Cannot access form here
  }, 
  timeout: 3000,
})

instance.interceptors.response.use(
  response => response,
  ({ message, response: { data, status } }) => {
    return handleError({ message, data, status })
  },
)

export default instance

我想访问 axios instance 中的 form 数据,以便能够在 headers 中使用 form._boundry

如何将 form 数据从 loginService.js 传递到 Services/index.js

这个问题似乎经常出现,但我似乎找不到规范的答案,所以这里...

当执行来自浏览器的 AJAX 请求时(通过 fetchXMLHttpRequest),运行时知道如何处理某些请求 body 格式并自动设置合适的Content-typeheader

  • 如果请求 body 是一个 FormData 实例,Content-type 将被设置为 multipart/form-data 并且还将包括适当的 mime 边界来自数据实例的标记。

    所有这些示例都将 post 数据作为 multipart/form-data 并适当 mime boundary tokens

    const body = new FormData();
    body.append("foo", "foo");
    body.append("bar", "bar");
    
    // fetch
    fetch(url, { method: "POST", body });
    
    // XMLHttpRequest
    const xhr = new XMLHttpRequest();
    xhr.open("POST", url);
    xhr.send(body);
    
    // Axios
    axios.post(url, body);
    
  • 如果请求body是一个URLSearchParams实例,Content-type将被设置为application/x-www-form-urlencoded

    所有这些例子都会post数据为application/x-www-form-urlencoded

    const body = new URLSearchParams({ foo: "foo", bar: "bar" });
    // serialises to "foo=foo&bar=bar"
    
    // fetch
    fetch(url, { method: "POST", body });
    
    // XMLHttpRequest
    const xhr = new XMLHttpRequest();
    xhr.open("POST", url);
    xhr.send(body);
    
    // Axios
    axios.post(url, body);
    

如果您打算以特定格式发送字符串数据,例如text/xmlapplication/json等,您只需要手动设置content-type,因为运行时无法推断类型来自数据。

const body = JSON.stringify({ foo: "foo", bar: "bar" });

// fetch
fetch(url, {
  method: "POST",
  headers: {
    "content-type": "application/json",
  },
  body
});

// XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.setRequestHeader("content-type", "application/json");
xhr.send(body);

在 Axios 上

Axios 为 POSTPUTPATCH 请求提供默认值 Accept: application/jsonContent-type: application/json。它还会自动将传递给 data 参数的 JavaScript 数据结构字符串化,因此在处理 JSON APIs

时只需要最少的配置
// no extra headers, no JSON.stringify()
axios.post(url, { foo: "foo", bar: "bar" })

在后台,Axios 使用 XMLHttpRequest,因此 FormDataURLSearchParams 的规范也适用。

Axios 0.27.1 已损坏

此特定版本的 Axios 无法使用 FormData 发出正确的请求。不要使用它!

NodeJS

当从后端使用 Axios 时,它不会从 FormData 个实例推断 Content-type headers。您可以使用请求拦截器解决此问题。

axios.interceptors.request.use(config => {
  if (config.data instanceof FormData) {
    Object.assign(config.headers, config.data.getHeaders());
  }
  return config;
}, null, { synchronous: true });

https://github.com/axios/axios#form-data


在 jQuery $.ajax()

jQuery 的 $.ajax() 方法(以及像 $.post() 这样的便捷方法)默认将请求 body 有效载荷发送为 application/x-www-form-urlencoded。 JavaScript 数据结构将使用 jQuery.param() 自动序列化,除非被告知不要这样做。如果想让浏览器根据body格式自动设置Content-typeheader,还需要在options

中配置
const body = new FormData()
body.append("foo", "foo")
body.append("bar", "bar")

$.ajax({
  url,
  method: "POST",
  data: body,
  contentType: false, // let the browser figure it out
  processData: false  // don't attempt to serialise data
})