geenpill
geenpill

Reputation: 115

Nesting a fetch promise inside another promise (React)?

I'm creating a simple React web app that will display Reddit content using Reddit's api.

handleLoad(event) {
    (() => {
        this.setState({
        isLoading: true
    });
    var newUrl = "https://www.reddit.com/r/" + this.state.search + ".json"
        return new Promise((resolve, reject) => {
            fetch(newUrl)
            .then((res) => {
                if(res.ok){
                    resolve(res.json())
                } else {
                    reject(res.status)
                }
            })
        }).then(data => {
            this.setState({
                info: data,
                isLoading: false,
                error: false
            })
        }).catch((message)=>{
            this.setState({
                isLoading: false,
                error: true
            })
        })
    })()
}

This code does work, but I'm wondering if maybe I'm doing too much? I wanted to be able to catch any errors (in cases where the subreddit doesn't exist or is being blocked) so that my app doesn't crash.

Upvotes: 1

Views: 399

Answers (2)

Ori Drori
Ori Drori

Reputation: 193002

Since fetch already returns a Promise, handle the response in another .then() block, you don't need to wrap it inside another promise.

Happy path:

  1. Call the API
  2. Parse the response as JSON
  3. Handle the successful response

The not so happy path: 1. Call the API 2. Check the res, and if it's not ok, throw an error with the status 3. The catch block will handle the thrown error

Example:

var newUrl = "https://www.reddit.com/r/emoji.json"

fetch(newUrl)
  .then(res => {
    if(!res.ok) throw new Error(res.status);
  })
  .then((res) => res.json()
  ).then(data => {
    console.log(data) // handle success
  }).catch((error) => {
    console.log(error.message) // handle failure
  })

Upvotes: 1

EugenSunic
EugenSunic

Reputation: 13723

The following should be enough.

If your promise succeeds, return a new JSON promise and set the state accordingly.

If not, throw an error and inside the catch block in which you're already handling the setState for that error.

handleLoad(event) {
  (() => {
    this.setState({
      isLoading: true
    });
    var newUrl = "https://www.reddit.com/r/" + this.state.search + ".json"

    fetch(newUrl)
      .then((res) => {
        if (res.ok) {
          return res.json()
        }
        throw new Error('failed')
      })
      .then(data => {
        this.setState({
          info: data,
          isLoading: false,
          error: false
        })
      }).catch((message) => {
        this.setState({
          isLoading: false,
          error: true
        })
      })
  })()
}

Upvotes: 2

Related Questions