对对,AbortControllerfetch 用来取消请求的控制器,不是拦截器。

最基础用法:

1
2
3
4
5
6
7
8
const controller = new AbortController()

fetch("/api/user", {
signal: controller.signal,
})

// 取消请求
controller.abort()

比如 3 秒超时自动取消:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const controller = new AbortController()

const timer = setTimeout(() => {
controller.abort()
}, 3000)

try {
const res = await fetch("/api/user", {
signal: controller.signal,
})

clearTimeout(timer)

const data = await res.json()
console.log(data)
} catch (err) {
if (err.name === "AbortError") {
console.log("请求被取消了")
} else {
console.error("请求失败", err)
}
}

封装成小工具:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
async function request(url, options = {}) {
const {
timeout = 5000,
...fetchOptions
} = options

const controller = new AbortController()

const timer = setTimeout(() => {
controller.abort()
}, timeout)

try {
const res = await fetch(url, {
...fetchOptions,
signal: controller.signal,
})

clearTimeout(timer)

if (!res.ok) {
throw new Error(`HTTP ${res.status}`)
}

return await res.json()
} catch (err) {
if (err.name === "AbortError") {
throw new Error("请求超时或已取消")
}

throw err
}
}

用法:

1
2
3
const data = await request("/api/user", {
timeout: 3000,
})

手动取消也可以:

1
2
3
4
5
6
7
8
const controller = new AbortController()

const promise = fetch("/api/search?q=abc", {
signal: controller.signal,
})

// 用户输入变化时取消旧请求
controller.abort()

在搜索框里很常见:用户连续输入时,取消上一次还没完成的请求,避免旧结果覆盖新结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let controller = null

async function search(keyword) {
if (controller) {
controller.abort()
}

controller = new AbortController()

try {
const res = await fetch(`/api/search?q=${keyword}`, {
signal: controller.signal,
})

const data = await res.json()
console.log(data)
} catch (err) {
if (err.name !== "AbortError") {
console.error(err)
}
}
}

小幽捏一下重点:
AbortController 主要管这几件事:

const controller = new AbortController()
controller.signal // 传给 fetch
controller.abort() // 取消 fetch

它不能“拦截”请求,但可以配合封装的 request 实现 超时取消、重复请求取消、组件卸载取消请求 这些效果。


本站由 楠瓜 使用 Stellar 1.33.1 主题创建。
风起于青萍之末,浪成于微澜之间。