[译]还在用XMLHttpRequest来做AJAX?试试Fetch吧!

Fetch API作为XMLHttpRequest的替代品,提供了一种更简洁、更优雅的方式来处理异步请求。本文介绍了Fetch API的基本用法,包括如何使用Promise进行结果处理,如何设置请求头,以及如何创建Request和Response对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于ajax,一个人尽皆知的秘密是,它的基础API:XMLHttpRequest,用它来做ajax请求实在是不太合适。我们已经在创造一个优雅的,关于xhr的一些API上做得很好了,但是我们能做得更好,而能让我们做得更好的就是使用fetch API!下面我们一起简单地看看这个新增的window.fetch方法,目前已经可以在Firefox和Chrome Canary上使用了。(注:现在已经可以在最新的Chrome稳定版本上使用)

XMLHttpRequest

在我看来XHR有点儿复杂了,而且我有点想吐槽的是,为什么XML是大写的,Http却是小写的???无论如何,这就是现在你用XHR时的写法:

//XHR,简直了。。。
if(window.XMLHttpRequest){
    //Mozilla,Safari...
    request = new XMLHttpRequest();
}else if(window.ActiveXObject){
    //IE下
    try{
        request = new ActiveXObject('Msxml2.XMLHTTP');
    }
    catch(e){
        try{
            request = new ActiveXObject('Microsoft.XMLHTTP');
        }
        catch(e){}
    }
}
//然后就是open,send
request.open('GET','https://davidwalsh.name/ajax-endpoint',true);
request.send(null);
复制代码

当然我们的js框架让我们使用XHR的方式变得更优雅了,但是从上面的例子你可以看出XHR真是一团糟。

基本的Fetch用法

在全局window作用域现在就提供了fetch方法,第一个参数是一个URL:

//url参数是必须的,而options是可选的
fetch('https://davidwalsh.name/some/url', {
	method: 'get'
}).then(function(response) {
	
}).catch(function(err) {
	// Error :(
});
复制代码

和最新的Battery API很像,fetch API 是使用Promise去处理结果或者回调的:

// 简单的响应处理
fetch('https://davidwalsh.name/some/url').then(function(response) {
	
}).catch(function(err) {
	// Error :(
});

// 挂上更“高级”的处理逻辑
fetch('https://davidwalsh.name/some/url').then(function(response) {
	return //...
}).then(function(returnedValue) {
	// ...
}).catch(function(err) {
	// Error :(
});
复制代码

如果你不习惯使用then,最好还是习惯一下吧。。。它很快就会无处不在

请求头

能够设置请求头对请求的灵活性来说很重要。你可以使用new Headers()来创建一个请求头

// 创建一个空的请求头实例
var headers = new Headers();

// 添加一些头部字段
headers.append('Content-Type', 'text/plain');
headers.append('X-My-Custom-Header', 'CustomValue');

// 检查、获取和设置头部的字段
headers.has('Content-Type'); // true
headers.get('Content-Type'); // "text/plain"
headers.set('Content-Type', 'application/json');

// 删除一个头部字段
headers.delete('X-My-Custom-Header');

// 添加初始化信息
var headers = new Headers({
	'Content-Type': 'text/plain',
	'X-My-Custom-Header': 'CustomValue'
});
复制代码

你可以用append,has,get,setdelete方法去更改请求头。可以通过创建一个请求实例去使用这个请求头。

var request = new Request('https://davidwalsh.name/some-url', {
	headers: new Headers({
		'Content-Type': 'text/plain'
	})
});

fetch(request).then(function() { /* 处理响应 */ });
复制代码

我们来看看Request和Response做了些什么吧!

Request

一个 Request 实例代表着一个 fetch 方法调用的片段。通过交给 fetch 一个 Request对象你可以创建一个高级的、定制的请求:

  • method - GET, POST, PUT, DELETE, HEAD
  • url - 请求的url
  • headers - 和Headers对象有关
  • referrer - 请求的referrer
  • mode - cors, no-cors, same-origin几个模式
  • credentials - 设置cookie是否随请求一起发送,当然了,有同源策略
  • redirect - follow, error, manual
  • integrity - SRI的值
  • cache - 缓存模式 (default, reload, no-cache)

一个简单的Request 用起来起来就像:

var request = new Request('https://davidwalsh.name/users.json', {
	method: 'POST', 
	mode: 'cors', 
	redirect: 'follow',
	headers: new Headers({
		'Content-Type': 'text/plain'
	})
});

// 现在,使用它!
fetch(request).then(function() { /* 处理响应 */ });
复制代码

只有第一个参数url是必须的。所有的属性会在Request实例创建后变成只读的状态。需要留意的是 Request 有一个 clone 方法,当在Service Worker API 中使用 fetch 时这个方法非常重要。因为一个 Request是一个stream,当另外一个fetch调用时必须被克隆。

fetch 方法的用法,表现得就像 Request一样,所以你可以这样做:

fetch('https://davidwalsh.name/users.json', {
	method: 'POST', 
	mode: 'cors', 
	redirect: 'follow',
	headers: new Headers({
		'Content-Type': 'text/plain'
	})
}).then(function() { /* 处理响应 */ });
复制代码

在Service Worker中你可能只会用到Request实例,因为Requestfetch的用法可以说是一样的。

Response

fetchthen方法提供了一个Response实例,但你可以手动创建一个Response对象——一种你可能会在使用service workers时遇到的情况。你可以这样设置Response:

  • type - basic, cors
  • url
  • useFinalURL - Boolean值,说明url是不是最后的URL
  • status - 状态码 (比如: 200, 404。。。)
  • ok - Boolean 值,是否成功响应 (200到299间的状态)
  • statusText - 状态码的文字描述 (比如: OK)
  • headers - 和response 关联的Headers 对象
// 创建你自己的响应,以测试Service worker
// new Response(BODY, OPTIONS)
var response = new Response('.....', {
	ok: false,
	status: 404,
	url: '/'
});

// fetch的then方法会拿到一个Response 实例
fetch('https://davidwalsh.name/')
	.then(function(responseObj) {
		console.log('status: ', responseObj.status);
	});
复制代码

Response 对象也提供了这些方法:

  • clone() - 创建一个Response对象的拷贝
  • error() - 返回一个新的关于网络错误的Response对象
  • redirect() - 创建一个新的不同url的响应
  • arrayBuffer() - 返回一个promise,一个携带ArrayBuffer的resolve
  • blob() - 返回一个promise,一个携带Blob的resolve
  • formData() - 返回一个返回一个promise,一个携带formData对象的resolve
  • json() - 返回一个返回一个promise对象,一个携带json的resolve
  • text() - 返回一个返回一个promise对象,一个携带USVString(text)的resolve

处理JSON

当你创建了一个请求,而请求的是JSON,那么它所得到的回调函数将具有把原始数据转换为JavaScript对象的json方法

fetch('https://davidwalsh.name/demo/arsenal.json').then(function(response) { 
	// Convert to JSON
	return response.json();
}).then(function(j) {
	// 没错,j是个JavaScript 对象
	console.log(j); 
});
复制代码

当然了,这就是一个简单的JSON.parse(jsonString),不过使用json方法是一条方便的捷径。

处理基本的文本/HTML响应

JSON 不会一直是我们期望的响应格式,所以这边你可以看看怎么处理文本或者HTML响应。


fetch('/next/page')
  .then(function(response) {
    return response.text();
  }).then(function(text) { 
  	// <!DOCTYPE ....
  	console.log(text); 
  });
复制代码

你可以通过在text()方法后链接上Promise的 then 方法来获得响应文本。

处理Blob响应

如果你想通过 fetch 来加载一张图片,就会有点区别,举个栗子:

fetch('https://davidwalsh.name/flowers.jpg')
  .then(function(response) {
    return response.blob();
  })
  .then(function(imageBlob) {
    document.querySelector('img').src = URL.createObjectURL(imageBlob);
  });
复制代码

响应的Blob() 方法接受一个Response流并将其读取完成。

发送From Data

另外一个通常会使用AJAX的情况就是发送From Data,这里我们来看看怎么用 fetch 方法来发送From Data:

fetch('https://davidwalsh.name/submit-json', {
	method: 'post',
	body: JSON.stringify({
		email: document.getElementById('email').value,
		answer: document.getElementById('answer').value
	})
});
复制代码

非常的简单,非常的赏心悦目!

不成文的小故事

或许 fetch 是一个更好的API,但这个API目前不支持取消请求,这会让很多开发者对它失望。

看起来使用这个新的 fetch API比起使用XHR来说更明智,更简单,托他的福我们可以更正确的去实现AJAX。fetch 有着“事后诸葛亮”的优势,尽管 fetch 还没被广泛支持,但我已经迫不及待了!

这是一篇关于 fetch 的介绍。想了解更多的话请移步到Introduction to Fetch。如果你想找 polyfill 的方案,可以看看GitHub's implementation

原文链接:davidwalsh.name/fetch

转载于:https://juejin.im/post/5bdc59cff265da610f632e21

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值