elbywan / wretch

A tiny wrapper built around fetch with an intuitive syntax. :candy:
MIT License
4.83k stars 98 forks source link

[Question] How to abort all pending requests? #85

Closed fragkp closed 4 years ago

fragkp commented 4 years ago

Hey,

First of all, thanks for this nice library!

On our current project, we want to abort all pending requests when the request fails with 429 (too many attempts).

Unfortunately, our attempt doesn't work.

const controller = new AbortController;

export default wretch()
    .signal(controller)
    .url('https://domain.com')
    ...
    .resolve(_ => _.error(429, error => {
        controller.abort();

        // handle error

        throw error;
    }));

Could you give us some insights about how to handle this case?

elbywan commented 4 years ago

Hey @fragkp,

First of all, thanks for this nice library!

Thanks 😄!

Could you give us some insights about how to handle this case?

Hmm I tried to reproduce but it seems to be working fine on my end. I can share what I did to test the feature though, maybe it could help you debug your project.


1) So first I've setup a small expressjs server that serves root / with a delay of one second and a 429 error when calling /429:

npm i express
const express = require('express')
const app = express()
const port = 8080

app.get('/', (req, res) => {
  setTimeout(() =>  res.send('Hello World!'), 1000)
})

app.get('/429', (req, res) => {
  res.status(429)
  res.send('Too Many Requests')
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})
# I named the file server.js (obviously)
node server.js

2) Then I opened my web browser, navigated to http://localhost:8080 and opened the browser console.

3) I made a small client with wretch using the code you pasted and executed that in the web console.

fetch('https://unpkg.com/wretch')
  .then(res => res.text())
  .then(eval)
  .then(() => {
    const controller = new AbortController()

    const request = wretch()
      .signal(controller)
      .url('http://localhost:8080')
      .resolve(_ => _.error(429, error => {
        controller.abort()
        throw error
      }));

    ['1', '2', '3'].forEach(count => {
      request.url('/').get().onAbort(() => console.log(`Aborted: ${count}`)).text(console.log)
    })
    request.url('/429').get().text(console.log)
  })

4) I checked both the network tab and the console and noticed that the requests were cancelled.

Capture d’écran 2020-08-03 à 18 08 04 Capture d’écran 2020-08-03 à 18 08 10
fragkp commented 4 years ago

Thanks for the fast response!

We found the bug on our side, so now it's all working as expected.