JavaScript fetch 快速入门
fetch API 简介
ECMAScript 2015(ES6) 标准的发布已经三年有余,现代浏览器对ES6语法的支持趋于完善,用Promise对象处理异步请求被越来越多的开发者应用。为了更好地处理异步请求,作为对现有的XMLHttpRequest
方法的替代,JavaScript引入了fetch
方法,基于Promise处理异步请求。
更多关于fetch的介绍,可以参考MDN关于fetch的介绍。
这篇文章假设你具备:
- 有JavaScript基础
- 对Promise对象有了解
如果你想了解Promise的相关知识,可以参考阮一峰老师的书籍
fetch 的浏览器支持情况
参考Can I Use,下图为本文写作时间(2018年12月14日)的支持情况,点击这里查看最新的支持情况
可以看到目前全球范围内支持已经达到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文件上传到了我的GitHub上,你可以点击这里查看它。
这个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文档中的说明:
在这里,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);
});
});
}
fetchClassic();
如果你喜欢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代码结果是一样的):
你可以在CodePen上看到这段代码的实际运行效果,并自己动手尝试一下。
用fetch和POST方法提交表单
接下来我将简短地介绍一下用fetch和HTTP POST方法来提交表单到服务器的方法,与上一个例子不同的是,我们这次要用到fetch的第二个参数来配置一下我们的请求。让我们假定提交表单的地址为https//example.billyzou.com/post
,在实际使用中,请把这个地址改成你服务器的地址。由于我们要用POST
方法而默认的方法为GET
,所以我们需要手动配置请求方法,同时我们还要在请求头中加上Content-Type
字段,这个字段的值要与请求体中的数据格式相同。
如果我们用JSON的形式提交表单:
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
,在实际操作时请根据你的选择来设置对应的请求头,以便服务器能正确地接收数据。
参考
欢迎大家访问我的GitHub主页来与我进行交流,地址是https://github.com/DaKoala