docs: add Response + Request API

This commit is contained in:
ruanyf
2023-09-09 19:46:22 +08:00
parent e826772a25
commit 6ff6cdbe48
5 changed files with 354 additions and 2 deletions

View File

@@ -1 +1 @@
Web API 教程,提供各种浏览器 API 文档,正在建设中。
Web API 文档,记录浏览器原生的各种 API 对象,正在建设中。

View File

@@ -7,6 +7,8 @@
- intl-relativetimeformat.md: Intl.RelativeTimeFormat
- page-lifecycle.md: Page Lifecycle API
- page-visibility.md: Page Visibility API
- request.md: Request API
- response.md: Response API
- server-sent-events.md: Server-Sent Events
- svg.md: SVG 图像
- websocket.md: WebSocket

View File

@@ -31,7 +31,7 @@ fetch('https://api.github.com/users/ruanyf')
.catch(err => console.log('Request Failed', err));
```
上面示例中,`fetch()`接收到的`response`是一个 [Stream 对象](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API)`response.json()`是一个异步操作,用来取出所有内容,并将其转为 JSON 对象。
上面示例中,`fetch()`接收到的`response`是一个 [Stream 对象](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API)里面的数据本例是 JSON 数据,所以使用`response.json()`方法,将其转为 JSON 对象。它是一个异步操作,返回一个 Promise 对象。
Promise 可以使用 await 语法改写,使得语义更清晰。

105
docs/request.md Normal file
View File

@@ -0,0 +1,105 @@
# Request API
浏览器原生提供 Request() 构造函数,用来构造发给服务器的 HTTP 请求。它生成的 Response 实例,可以作为`fetch()`的参数。
## 构造方法
Request 作为构造函数的语法如下,返回一个 Request 实例对象。
```javascript
new Request(url: String, [init: Object]): Request
```
它的第一个参数是请求的 URL 字符串,第二个参数是一个可选的对象,用来构造 HTTP 请求,它的类型如下。
```javascript
{
body : Object // 发送的数据体,必须是 Blob、BufferSource、FormData、String、URLSearchParams 类型之一
cache : String
credentials : String
headers : Object
integrity : String
keepalive : Boolean
method : String // HTTP 方法,必须是 'GET'、'POST'、'DELETE' 等值
mode : String
redirect : String // 必须是 'follow'、'error'、'manual' 之一
referrer : String
referrerPolicy : String
requestMode : String
requestCredentials : String
signal : AbortSignal
}
```
它的第一个参数也可以是另一个 Request 对象,通过第二个参数对其进行修改。
```javascript
new Request(request: Request, [init: Object]): Request
```
## 实例属性
- bodyUsed : Boolean readonly
- cache : String readonly。Will be one of: 'default', 'force-cache', 'no-cache', 'no-store', 'only-if-cached', 'reload'.
- credentials : String readonly。Will be one of: 'include', 'omit', 'same-origin'.
- destination : String readonly。Will be one of: '', 'audio', 'audioworklet', 'document', 'embed', 'font', 'frame', 'iframe', 'image', 'manifest', 'object', 'paintworklet', 'report', 'script', 'sharedworker', 'style', 'track', 'video', 'worker', 'xslt'.
- headers : Headers readonly。
- integrity : String readonly。
- isHistoryNavigation : Boolean readonly。
- isReloadNavigation : Boolean readonly。
- keepalive : Boolean readonly。
- method : String readonly。
- mode : String readonly。Will be one of: 'same-origin', 'no-cors', 'cors'.
- redirect : String readonly。
- referrer : String readonly。
- referrerPolicy : String readonly。
- signal : AbortSignal readonly。
- url : String readonly。
## 实例方法
### 取出数据体
- arrayBuffer():返回一个 Promise 对象,将 Request 的数据体作为 ArrayBuffer 对象返回。
- blob():返回一个 Promise 对象,将 Request 的数据体作为 Blob 对象返回。
- json():返回一个 Promise 对象,将 Request 的数据体作为 JSON 对象返回。
- text():返回一个 Promise 对象,将 Request 的数据体作为字符串返回。
- formData():返回一个 Promise 对象,将 Request 的数据体作为表单数据 FormData 对象返回。
`.formData()`方法返回一个 Promise 对象,最终得到的是一个 FormData 表单对象,里面是用键值对表示的各种表单元素。
该方法很少使用,因为需要拦截发给服务器的请求的场景不多,一般用在 Service Worker。它需要拦截和处理网络请求修改表单数据然后将修改后的表单数据发送到服务器。
下面是 Service Worker 拦截表单提交请求,并使用`.formData()`方修改表单数据的例子。
```javascript
self.addEventListener('fetch', event => {
// 拦截表单提交请求
if (
event.request.method === 'POST' &&
event.request.headers.get('Content-Type') === 'application/x-www-form-urlencoded'
) {
event.respondWith(handleFormSubmission(event.request));
}
});
async function handleFormSubmission(request) {
const formData = await request.formData();
formData.append('extra-field', 'extra-value');
const newRequest = new Request(request.url, {
method: request.method,
headers: request.headers,
body: new URLSearchParams(formData)
});
return fetch(newRequest);
}
```
上面示例中Service Worker 拦截表单请求以后,添加了一个表单成员,再调用`fetch()`向服务器发出修改后的请求。
### clone()
`clone()`用来复制 HTTP 请求对象。

245
docs/response.md Normal file
View File

@@ -0,0 +1,245 @@
# Response API
浏览器原生提供`Response()`构造函数,用来构造服务器响应。
`fetch()`方法返回的就是一个 Response 对象。
## 构造方法
`Response()`作为构造方法调用时,返回 Response 实例。
```javascript
// 定义
new Response([body:Object, [init : Object]]): Response
// 用法
new Response()
new Response(body)
new Response(body, options)
```
它带有两个参数,都是可选的。
第一个参数`body`是一个对象代表服务器返回的数据体必须是下面类型之一ArrayBuffer、ArrayBufferView、Blob、FormData、ReadableStream、String、URLSearchParams。
第二个参数`init`是一个对象,代表服务器返回的数据头,类型描述如下。
```javascript
{
status : Number
statusText : String
headers : Object
}
```
下面是一个例子。
```javascript
const myBlob = new Blob();
const myOptions = { status: 200, statusText: "OK" };
const myResponse = new Response(myBlob, myOptions);
```
## 实例属性
### bodybodyUsed
`body`属性代表数据体,是一个只读的 ReadableStream 对象。
```javascript
const res = await fetch('/fireworks.ogv');
const reader = res.body.getReader();
let result;
while (!(result = await reader.read()).done) {
console.log('chunk size:', result.value.byteLength);
}
```
上面示例中,先建立一个 body 的读取器,然后每次读取一段数据,输出这段数据的字段长度。
注意,`body`是一个 Stream 对象,只能读取一次。取出所有数据以后,第二次就读不到了。
`bodyUsed`属性是一个只读的布尔值,表示`body`属性是否已经读取。
### headers
`headers`属性代表服务器返回的数据头,是一个只读的 Headers 对象。
```javascript
const res = await fetch('/flowers.jpg');
console.log(...res.headers);
```
上面示例中,发出请求后,展开打印`res.headers`属性,即服务器回应的所有消息头。
### ok
`ok`属性是一个布尔值表示服务器返回的状态码是否成功200到299该属性只读。
```javascript
const res1 = await fetch('https://httpbin.org/status/200');
console.log(res1.ok); // true
const res2 = await fetch('https://httpbin.org/status/404');
console.log(res2.ok); // false
```
### redirected
`redirected`是一个布尔值表示服务器返回的状态码是否跳转类型301302等该属性只读。
```javascript
const res1 = await fetch('https://httpbin.org/status/200');
console.log(res1.redirected); // false
const res2 = await fetch('https://httpbin.org/status/301');
console.log(res2.redirected); // true
```
### statusstatusText
`status`属性是一个数值,代表服务器返回的状态码,该属性只读。
```javascript
const res1 = await fetch('https://httpbin.org/status/200');
console.log(res1.status); // 200
const res2 = await fetch('https://httpbin.org/status/404');
console.log(res2.status); // 404
```
`statusText`属性是一个字符串代表服务器返回的状态码的文字描述。比如状态码200的`statusText`一般是`OK`,也可能为空。
### type
`type`属性是一个只读字符串表示服务器回应的类型它的值有下面几种basic、cors、default、error、opaque、opaqueredirect。
### url
`url`属性是一个字符串,代表服务器路径,该属性只读。如果请求是重定向的,该属性就是重定向后的 URL。
## 实例方法
### 数据读取
以下方法可以获取服务器响应的消息体,根据返回数据的不同类型,调用相应方法。
- .json():返回一个 Promise 对象,最终得到一个解析后的 JSON 对象。
- .text():返回一个 Promise 对象,最终得到一个字符串。
- .blob():返回一个 Promise 对象,最终得到一个二进制 Blob 对象,代表某个文件整体的原始数据。
- .arrayBuffer():返回一个 Promise 对象,最终得到一个 ArrayBuffer 对象,代表一段固定长度的二进制数据。
- .formData():返回一个 Promise 对象,最终得到一个 FormData 对象,里面是键值对形式的表单提交数据。
下面是从服务器获取 JSON 数据的一个例子,使用`.json()`方法,其他几个方法的用法都大同小异。
```javascript
async function getRedditPosts() {
try {
const response = await fetch('https://www.reddit.com/r/all/top.json?limit=10');
const data = await response.json();
const posts = data.data.children.map(child => child.data);
console.log(posts.map(post => post.title));
} catch (error) {
console.error(error);
}
}
```
下面是从服务器获取二进制文件的例子,使用`.blob()`方法。
```javascript
async function displayImageAsync() {
try {
const response = await fetch('https://www.example.com/image.jpg');
const blob = await response.blob();
const url = URL.createObjectURL(blob);
const img = document.createElement('img');
img.src = url;
document.body.appendChild(img);
} catch (error) {
console.error(error);
}
}
```
下面是从服务器获取音频文件,直接解压播放的例子,使用`.arrayBuffer()`方法。
```javascript
async function playAudioAsync() {
try {
const response = await fetch('https://www.example.com/audio.mp3');
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await new AudioContext().decodeAudioData(arrayBuffer);
const source = new AudioBufferSourceNode(new AudioContext(), { buffer: audioBuffer });
source.connect(new AudioContext().destination);
source.start(0);
} catch (error) {
console.error(error);
}
}
```
### clone()
`clone()`方法用来复制 Response 对象。
```javascript
const res1 = await fetch('/flowers.jpg');
const res2 = res1.clone();
```
复制以后,读取一个对象的数据,不会影响到另一个对象。
## 静态方法
### Response.json()
`Response.json()`返回一个 Response 实例,该实例对象的数据体就是作为参数的 JSON 数据,数据头的`Content-Type`字段自动设为`application/json`
```javascript
Response.json(data)
Response.json(data, options)
```
`Response.json()`基本上就是`Response()`构造函数的变体。
下面是示例。
```javascript
const jsonResponse1 = Response.json({ my: "data" });
const jsonResponse2 = Response.json(
{ some: "data", more: "information" },
{ status: 307, statusText: "Temporary Redirect" },
);
```
### Response.error()
`Response.error()`用来构造一个表示报错的服务器回应,主要用在 Service worker表示拒绝发送。
```javascript
self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url);
if (url.pathname === '/flowers.jpg') {
event.respondWith(Response.error());
}
});
```
### Response.redirect()
`Response.redirect()`用来构造一个表示跳转的服务器回应,主要用在 Service worker表示跳转到其他网址。
```javascript
Response.redirect(url)
Response.redirect(url, status)
```
这个方法的第一个参数`url`是所要跳转的目标网址第二个参数是状态码一般是301或302默认值
```javascript
Response.redirect("https://www.example.com", 302);
```