我试图使用fetch POST一个JSON对象。

根据我的理解,我需要将一个字符串化的对象附加到请求的主体,例如:

fetch("/echo/json/",
{
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    method: "POST",
    body: JSON.stringify({a: 1, b: 2})
})
.then(function(res){ console.log(res) })
.catch(function(res){ console.log(res) })

当使用jsfiddle的JSON回显时,我希望看到我发送的对象({a: 1, b: 2})回来,但这不会发生- chrome devtools甚至不显示JSON作为请求的一部分,这意味着它没有被发送。


当前回答

你可以用await/async做得更好。

http请求参数:

const _url = 'https://jsonplaceholder.typicode.com/posts';
let _body = JSON.stringify({
  title: 'foo',
  body: 'bar',
  userId: 1,
});
  const _headers = {
  'Content-type': 'application/json; charset=UTF-8',
};
const _options = { method: 'POST', headers: _headers, body: _body };

使用干净的async/await语法:

const response = await fetch(_url, _options);
if (response.status >= 200 && response.status <= 204) {
  let data = await response.json();
  console.log(data);
} else {
  console.log(`something wrong, the server code: ${response.status}`);
}

使用老式fetch().then().then():

fetch(_url, _options)
  .then((res) => res.json())
  .then((json) => console.log(json));

其他回答

2021年的答案:以防你在这里寻找如何使用async/await或promises来进行GET和POST Fetch api请求,而不是axios。

我使用jsonplaceholder伪API来演示:

使用async/await获取api GET请求:

         const asyncGetCall = async () => {
            try {
                const response = await fetch('https://jsonplaceholder.typicode.com/posts');
                 const data = await response.json();
                // enter you logic when the fetch is successful
                 console.log(data);
               } catch(error) {
            // enter your logic for when there is an error (ex. error toast)
                  console.log(error)
                 } 
            }


          asyncGetCall()

使用async/await获取api POST请求:

    const asyncPostCall = async () => {
            try {
                const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
                 method: 'POST',
                 headers: {
                   'Content-Type': 'application/json'
                   },
                   body: JSON.stringify({
             // your expected POST request payload goes here
                     title: "My post title",
                     body: "My post content."
                    })
                 });
                 const data = await response.json();
              // enter you logic when the fetch is successful
                 console.log(data);
               } catch(error) {
             // enter your logic for when there is an error (ex. error toast)

                  console.log(error)
                 } 
            }

asyncPostCall()

使用Promises获取请求:

  fetch('https://jsonplaceholder.typicode.com/posts')
  .then(res => res.json())
  .then(data => {
   // enter you logic when the fetch is successful
    console.log(data)
  })
  .catch(error => {
    // enter your logic for when there is an error (ex. error toast)
   console.log(error)
  })

使用承诺POST请求:

fetch('https://jsonplaceholder.typicode.com/posts', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
   body: JSON.stringify({
     // your expected POST request payload goes here
      title: "My post title",
      body: "My post content."
      })
})
  .then(res => res.json())
  .then(data => {
   // enter you logic when the fetch is successful
    console.log(data)
  })
  .catch(error => {
  // enter your logic for when there is an error (ex. error toast)
   console.log(error)
  })  

使用Axios获取请求:

        const axiosGetCall = async () => {
            try {
              const { data } = await axios.get('https://jsonplaceholder.typicode.com/posts')
    // enter you logic when the fetch is successful
              console.log(`data: `, data)
           
            } catch (error) {
    // enter your logic for when there is an error (ex. error toast)
              console.log(`error: `, error)
            }
          }
    
    axiosGetCall()

使用Axios的POST请求:

const axiosPostCall = async () => {
    try {
      const { data } = await axios.post('https://jsonplaceholder.typicode.com/posts',  {
      // your expected POST request payload goes here
      title: "My post title",
      body: "My post content."
      })
   // enter you logic when the fetch is successful
      console.log(`data: `, data)
   
    } catch (error) {
  // enter your logic for when there is an error (ex. error toast)
      console.log(`error: `, error)
    }
  }


axiosPostCall()

这与内容类型有关。正如你可能已经从其他讨论和这个问题的答案中注意到的,有些人能够通过设置Content-Type: 'application/json'来解决这个问题。不幸的是,在我的情况下,它没有工作,我的POST请求在服务器端仍然是空的。

然而,如果你尝试使用jQuery的$.post(),它可以工作,原因可能是因为jQuery使用Content-Type: 'x-www-form-urlencoded'而不是application/json。

data = Object.keys(data).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(data[key])).join('&')
fetch('/api/', {
    method: 'post', 
    credentials: "include", 
    body: data, 
    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})

从搜索引擎,我结束了这个主题的非json发布数据与fetch,所以我认为我将添加这个。

对于非json,你不必使用表单数据。你可以简单地设置Content-Type头为application/x-www-form-urlencoded,并使用一个字符串:

fetch('url here', {
    method: 'POST',
    headers: {'Content-Type':'application/x-www-form-urlencoded'}, // this line is important, if this content-type is not set it wont work
    body: 'foo=bar&blah=1'
});

构建body字符串的另一种方法是使用库,而不是像上面那样将其输入。例如query-string或qs包中的stringify函数。所以使用它看起来像这样:

import queryString from 'query-string'; // import the queryString class

fetch('url here', {
    method: 'POST',
    headers: {'Content-Type':'application/x-www-form-urlencoded'}, // this line is important, if this content-type is not set it wont work
    body: queryString.stringify({for:'bar', blah:1}) //use the stringify object of the queryString class
});

你可以用await/async做得更好。

http请求参数:

const _url = 'https://jsonplaceholder.typicode.com/posts';
let _body = JSON.stringify({
  title: 'foo',
  body: 'bar',
  userId: 1,
});
  const _headers = {
  'Content-type': 'application/json; charset=UTF-8',
};
const _options = { method: 'POST', headers: _headers, body: _body };

使用干净的async/await语法:

const response = await fetch(_url, _options);
if (response.status >= 200 && response.status <= 204) {
  let data = await response.json();
  console.log(data);
} else {
  console.log(`something wrong, the server code: ${response.status}`);
}

使用老式fetch().then().then():

fetch(_url, _options)
  .then((res) => res.json())
  .then((json) => console.log(json));

如果你使用纯json REST API,我已经在fetch()周围创建了一个薄包装器,其中有许多改进:

// Small library to improve on fetch() usage
const api = function(method, url, data, headers = {}){
  return fetch(url, {
    method: method.toUpperCase(),
    body: JSON.stringify(data),  // send it as stringified json
    credentials: api.credentials,  // to keep the session on the request
    headers: Object.assign({}, api.headers, headers)  // extend the headers
  }).then(res => res.ok ? res.json() : Promise.reject(res));
};

// Defaults that can be globally overwritten
api.credentials = 'include';
api.headers = {
  'csrf-token': window.csrf || '',    // only if globally set, otherwise ignored
  'Accept': 'application/json',       // receive json
  'Content-Type': 'application/json'  // send json
};

// Convenient methods
['get', 'post', 'put', 'delete'].forEach(method => {
  api[method] = api.bind(null, method);
});

要使用它,你有变量api和4个方法:

api.get('/todo').then(all => { /* ... */ });

在一个async函数中:

const all = await api.get('/todo');
// ...

jQuery示例:

$('.like').on('click', async e => {
  const id = 123;  // Get it however it is better suited

  await api.put(`/like/${id}`, { like: true });

  // Whatever:
  $(e.target).addClass('active dislike').removeClass('like');
});