fetch API 简介
ECMAScript 2015(ES6) 标准的发布已经三年有余,现代浏览器对ES6语法的支持趋于完善,用Promise对象处理异步请求被越来越多的开发者应用。为了更好地处理异步请求,作为对现有的XMLHttpRequest方法的替代,JavaScript引入了fetch方法,基于Promise处理异步请求。

更多关于fetch的介绍,可以参考MDN关于fetch的介绍。

这篇文章假设你具备:

有JavaScript基础
对Promise对象有了解
如果你想了解Promise的相关知识,可以参考阮一峰老师的书籍

fetch 的浏览器支持情况
参考Can I Use,下图为本文写作时间 的支持情况,点击这里查看最新的支持情况
1.png
可以看到目前全球范围内支持已经达到87.84%,在中国也有69.65%的支持,并且将来这个数据必然会继续升高,已经广泛地被主流浏览器所支持(IE除外)。

使用fetch
fetch接受两个参数,url和init,其中url参数是必须的,而init参数是可选的。

url参数是一个字符串,表示请求的url地址,而init是一个对象,在里面可以对这个请求进行配置,例如设置请求方法,设置请求头等,如果不传入init参数,将会采用默认的配置,可以点击这里查看MDN文档对fetch第二个参数的说明以及默认配置。

返回一个包含Promise对象,在这个对象的resolve方法中可以访问到请求的结果,是一个Response对象,可以点击这里查看MDN文档对Response对象的属性和方法的具体说明。

你无须对fetch的配置以及Response十分熟悉,也可以方便地使用fetch,使用默认的配置即可完成很多工作,当你有特定需求时再回过头来了解细节即可,接下来我们来写一个最简单的fetch。

一个最简单的fetch
让我们来写一个最简单的fetch,从服务器上获取一个json文件并打印出来,你可以点击这里查看它。
这个JSON文件是这样的:

[
  {
    "name": "张三",
    "age": 18
  },
  {
    "name": "李四",
    "age": 20
  },
  {
    "name": "王五",
    "age": 22
  }
]

现在我们用fetch获取这个文件,并把它打印出来,要知道,fetch默认使用的是GET方法,所以在这里我们不需要第二个参数就可以达到我们的目的。

fetch('https://raw.githubusercontent.com/DaKoala/fetch-example/master/people.json')
    .then(res => res.json())
    .then(json => console.log(json))
    // [{ name: "张三", age: 18 }, { name: "李四", age: 20 }, { name: "王五", age: 22 }]

请注意,这里我们调用了then方法2次,在第一个then中,我们得到了一个Response对象,我们调用它的.json()方法,来获取服务器响应中的数据,需要注意的是,res.json()返回的是一个Promise对象,而不是JSON化的数据,参考MDN文档中的说明:
2.png
在这里,res.json()返回了一个Promise对象,在这个Promise对象的then方法中我们可以访问到被解析成JSON格式的数据,这时候我们才可以使用这些数据,因此要一个Promise链,总共调用两次then方法。
如果你喜欢最新的async/await语法,我们也可以换一种风格完成同样的事情,就像这样:

(async () => {
    const res = await fetch('https://raw.githubusercontent.com/DaKoala/fetch-example/master/people.json');
    const json = await res.json();
    console.log(json);
    // [{ name: "张三", age: 18 }, { name: "李四", age: 20 }, { name: "王五", age: 22 }]
})();

由于await关键词只能在async函数中出现,所以我在这里写了一个包含async关键词的立即执行函数表达式(IIFE),这个代码的效果与上文出现的Promise风格的代码一致。

如果你想了解async/await相关的知识,可以参考阮一峰老师的书籍。

在浏览器中用fetch获取数据
让我们继续使用刚才的JSON文件,这次我们在浏览器中进行同样的操作,并将结果加进HTML中,也就是说,我们用fetch进行一个AJAX请求。

HTML文件

<h1>Fetch示例</h1>
<div id="container"></div>

JavaScript文件

function fetchClassic() {
  fetch('https://raw.githubusercontent.com/DaKoala/fetch-example/master/people.json')
  .then(res => res.json())
  .then(json => {
    const container = document.getElementById('container');
    json.forEach(item => {
      const element = document.createElement('p');
      element.textContent = `${item.name} - ${item.age}岁`;
      container.appendChild(element);
    });
  });
}

如果你喜欢async/await风格,你可以这样写:

async function fetchAsync() {
  const res = await fetch('https://raw.githubusercontent.com/DaKoala/fetch-example/master/people.json');
  const json = await res.json();
  const container = document.getElementById('container');
    json.forEach(item => {
      const element = document.createElement('p');
      element.textContent = `${item.name} - ${item.age}岁`;
      container.appendChild(element);
    });
}

fetchAsync();

运行结果(两种风格的JavaScript代码结果是一样的):

const data = { name: 'Billy', age: 18 };
fetch('https//example.billyzou.com/post', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringfy(data), // "{"name":"Billy","age":18}"
})

如果我们用form的格式提交表单:
const data = { name: 'Billy', age: 18 };
function formatData(data) {

const result = Object.entries(data).map(([key, value]) => `${key}=${value}`).join('&');
return result;

}

fetch('https//example.billyzou.com/post', {
method: 'POST',
headers: {

'Content-Type': 'application/x-www-form-urlencoded',

},
body: formatData(data), // "name=Billy&age=18"
})
注意两种方法中由于数据格式不同,请求头中的Content-Type字段对应被设置为了application/json和application/x-www-form-urlencoded,在实际操作时请根据你的选择来设置对应的请求头,以便服务器能正确地接收数据。

标签: none

添加新评论