fetch请求是什么:
fetch 是一种用于发起网络请求的现代 JavaScript API,它旨在替代较为老旧的 XMLHttpRequest。fetch 提供了一种更强大、灵活的方法来获取资源,并且基于Promise,使得代码更加简洁和易于阅读。
以下是 fetch 的一些关键特点:
- 基于 Promise:
fetch返回一个 Promise,该 Promise 会在响应被成功返回时解析为Response对象。这意味着你可以使用.then()方法链式处理请求结果,也可以使用async/await语法来简化异步操作。 - 支持多种HTTP方法:虽然
fetch默认是 GET 请求,但你也可以轻松地发送 POST 或其他类型的 HTTP 请求,只需要在选项对象中指定method参数。 - 更简单的接口:与
XMLHttpRequest相比,fetch拥有更简单的接口和更少的配置选项,这使得它更容易上手和使用。 - 更好的错误处理:
fetch只在网络请求失败(例如,DNS 查询失败、连接失败等)时才会拒绝(reject)Promise。对于 HTTP 错误状态码(如 404 或 500),fetch的 Promise 仍然会成功解决(resolve),因此你需要检查Response.ok属性来判断是否发生了 HTTP 错误。 - 流式数据读取:
fetch还允许通过response.body和ReadableStream接口来流式读取大文件或服务器推送的数据。 - 不自动携带凭证:默认情况下,
fetch不会发送 cookies 等凭据信息,除非你显式设置了credentials: 'include'选项。 - 无跨域资源共享 (CORS) 支持:
fetch遵循同源策略,并且可以处理跨域请求,只要服务器正确配置了 CORS 头。
这里是一个使用 fetch 发起 GET 请求的基本例子:
javascript
深色版本
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json(); // 如果响应内容是 JSON 格式,则解析为 JavaScript 对象
})
.then(data => console.log(data))
.catch(error => console.error('There has been a problem with your fetch operation:', error));
以及一个发起 POST 请求的例子:
javascript
深色版本
fetch('https://api.example.com/post', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
key1: 'value1',
key2: 'value2'
})
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
fetch API 在现代浏览器中得到了广泛的支持,但对于非常老的浏览器可能需要使用 polyfill 来提供兼容性。
使用fetch请求接收EventStream中服务器返回的流式数据示例
使用 fetch API 来接收服务器发送的事件流(Server-Sent Events, SSE),即 EventStream,可以通过创建一个持续开放的 HTTP 连接来实现,这个连接允许服务器向客户端推送更新。不过需要注意的是,fetch 本身并不是为了处理 SSE 而设计的,它更适合于一次性的请求-响应模式。但是,你可以通过设置 response.body 并读取 ReadableStream 来处理 SSE。
下面是一个简单的例子,展示了如何使用 fetch 和 Response.body 来监听来自服务器的事件流:
javascript
深色版本
if (!('fetch' in window)) {
console.error('Fetch API is not supported in this browser.');
}
function createEventSource(url) {
const eventSource = new AbortController();
const signal = eventSource.signal;
fetch(url, { signal })
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// Read the response as a stream.
const reader = response.body.getReader();
const decoder = new TextDecoder('utf-8');
function readStream() {
reader.read().then(({ done, value }) => {
if (done) {
console.log('Stream complete');
return;
}
// Decode and process each chunk of data.
const decodedValue = decoder.decode(value, { stream: true });
processEventStreamData(decodedValue);
// Continue reading the stream.
readStream();
}).catch(err => {
if (err.name !== 'AbortError') {
console.error('Reading stream failed:', err);
}
});
}
readStream();
// Return a function to abort the connection.
return () => {
eventSource.abort();
console.log('Connection aborted');
};
})
.catch(error => {
console.error('Failed to fetch the event source:', error);
});
return eventSource;
}
// Function to handle incoming data from the stream.
function processEventStreamData(data) {
// Implement your logic here for processing each message.
console.log('Received data:', data);
}
// Start listening to the server-sent events.
const stopListening = createEventSource('/event-stream-endpoint');
// You can later call `stopListening()` to close the connection.
请注意,这段代码没有直接利用浏览器内置的 EventSource 对象,该对象是专门为 SSE 设计的,并且提供了更简洁的接口。如果你的目标是与 SSE 工作,那么建议你使用 EventSource。上述方法仅适用于需要更多控制或自定义的情况,或者在某些情况下 EventSource 不可用时。
要使用 EventSource,代码会更加简洁:
javascript
深色版本
const eventSource = new EventSource('/event-stream-endpoint');
eventSource.onmessage = function(event) {
console.log('New message:', event.data);
};
eventSource.onerror = function(error) {
console.error('EventSource failed:', error);
};
// When you want to disconnect:
// eventSource.close();