mirror of
https://github.com/wangdoc/webapi-tutorial.git
synced 2025-12-20 00:59:54 +08:00
docs: add Response + Request API
This commit is contained in:
@@ -1 +1 @@
|
||||
Web API 教程,提供各种浏览器 API 文档,正在建设中。
|
||||
Web API 文档,记录浏览器原生的各种 API 对象,正在建设中。
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
105
docs/request.md
Normal 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
245
docs/response.md
Normal 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);
|
||||
```
|
||||
|
||||
## 实例属性
|
||||
|
||||
### body,bodyUsed
|
||||
|
||||
`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`是一个布尔值,表示服务器返回的状态码是否跳转类型(301,302等),该属性只读。
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
### status,statusText
|
||||
|
||||
`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);
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user