iT邦幫忙

2023 iThome 鐵人賽

DAY 9
0
Modern Web

前端知識系列 第 23

如何使用 Promise.race + AbortController 取消多個過長請求

  • 分享至 

  • xImage
  •  

Yes

可以使用 AbortController 來取消過長的要求,但是當有多個要求時,寫起來會很麻煩。

const Component() => {
  const controller = new AbortController()
  const fetchData = async () => {
    setTimeout(() {
      =>
      controller.abort()
    }, 2000)
    await fetch("/api/example", {
      signal: controller.signal
    })
  }
  return <button onClick = {
    fetchData
  } > fetch data < /button>
}

可以使用 Promise.race 來限制請求的最長的時間,例如下方當請求都大於 1000 ms,reject 會先被回傳,
然而這樣並沒有真的取消那些請求,它們還是在 pending
( 好比賽跑比賽,當第一名的人跑完了,其他人也還是在跑 )。

export default function Home() {
  const fetchData = async () => {
    try {
      await Promise.race([fetch('/api/example'),
        fetch('/api/2'),
        fetch('/api/3'),
        fetch('/api/4'),
        fetch('/api/4'),
        new Promise((_, reject) => setTimeout(reject, 1000))
      ])

    } catch (err) {
      console.log('promise rejected')
    }


    return <button onClick = {
      fetchData
    } > fetch data < /button>
  }
}

因此可以加上 AbortController,當 reject 先被回傳時,可以把所有還在 pending 的請求取消。
( 好比賽跑比賽,當第一名的人跑完了,其他人會被強制結束比賽 )。

export default function Home() {
  const controller = new AbortController()
  const fetchData = async () => {
    try {
      await Promise.race([
        fetch('/api/example', {
          signal: controller.signal
        }),
        fetch('/api/example', {
          signal: controller.signal
        }), fetch('/api/example', {
          signal: controller.signal
        }),
        fetch('/api/example', {
          signal: controller.signal
        }),
        new Promise((reject) => setTimeout(reject, 2000)),
      ])
    } catch (err) {
      B controller.abort()
    }

    return <button onClick = {
      fetchData
    } > fetch data < /button>
  }
}

上一篇
2023/10/11
下一篇
PromiseAll-vs-AllSettled-Demo
系列文
前端知識30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言