Fetch: reject promise and catch the error if status is not OK?

前端 未结 4 582
抹茶落季
抹茶落季 2020-11-28 22:50

Here\'s what I have going:

import \'whatwg-fetch\';

function fetchVehicle(id) {
    return dispatch => {
        return dispatch({
            type: \'FE         


        
相关标签:
4条回答
  • 2020-11-28 23:35

    I just checked the status of the response object:

    $promise.then( function successCallback(response) {  
      console.log(response);
      if (response.status === 200) { ... }
    });
    
    0 讨论(0)
  • 2020-11-28 23:41

    For me, fny answers really got it all. since fetch is not throwing error, we need to throw/handle the error ourselves. Posting my solution with async/await. I think it's more strait forward and readable

    Solution 1: Not throwing an error, handle the error ourselves

      async _fetch(request) {
        const fetchResult = await fetch(request); //Making the req
        const result = await fetchResult.json(); // parsing the response
    
        if (fetchResult.ok) {
          return result; // return success object
        }
    
    
        const responseError = {
          type: 'Error',
          message: result.message || 'Something went wrong',
          data: result.data || '',
          code: result.code || '',
        };
    
        const error = new Error();
        error.info = responseError;
    
        return (error);
      }
    

    Here if we getting an error, we are building an error object, plain JS object and returning it, the con is that we need to handle it outside. How to use:

      const userSaved = await apiCall(data); // calling fetch
      if (userSaved instanceof Error) {
        debug.log('Failed saving user', userSaved); // handle error
    
        return;
      }
      debug.log('Success saving user', userSaved); // handle success
    

    Solution 2: Throwing an error, using try/catch

    async _fetch(request) {
        const fetchResult = await fetch(request);
        const result = await fetchResult.json();
    
        if (fetchResult.ok) {
          return result;
        }
    
        const responseError = {
          type: 'Error',
          message: result.message || 'Something went wrong',
          data: result.data || '',
          code: result.code || '',
        };
    
        let error = new Error();
        error = { ...error, ...responseError };
        throw (error);
      }
    

    Here we are throwing and error that we created, since Error ctor approve only string, Im creating the plain Error js object, and the use will be:

      try {
        const userSaved = await apiCall(data); // calling fetch
        debug.log('Success saving user', userSaved); // handle success
      } catch (e) {
        debug.log('Failed saving user', userSaved); // handle error
      }
    

    Solution 3: Using customer error

      async _fetch(request) {
        const fetchResult = await fetch(request);
        const result = await fetchResult.json();
    
        if (fetchResult.ok) {
          return result;
        }
    
        throw new ClassError(result.message, result.data, result.code);
      }
    

    And:

    class ClassError extends Error {
    
      constructor(message = 'Something went wrong', data = '', code = '') {
        super();
        this.message = message;
        this.data = data;
        this.code = code;
      }
    
    }
    

    Hope it helped.

    0 讨论(0)
  • 2020-11-28 23:43

    Fetch promises only reject with a TypeError when a network error occurs. Since 4xx and 5xx responses aren't network errors, there's nothing to catch. You'll need to throw an error yourself to use Promise#catch.

    A fetch Response conveniently supplies an ok , which tells you whether the request succeeded. Something like this should do the trick:

    fetch(url).then((response) => {
      if (response.ok) {
        return response.json();
      } else {
        throw new Error('Something went wrong');
      }
    })
    .then((responseJson) => {
      // Do something with the response
    })
    .catch((error) => {
      console.log(error)
    });
    
    0 讨论(0)
  • 2020-11-28 23:45

    Thanks for the help everyone, rejecting the promise in .catch() solved my issue:

    export function fetchVehicle(id) {
        return dispatch => {
            return dispatch({
                type: 'FETCH_VEHICLE',
                payload: fetch(`http://swapi.co/api/vehicles/${id}/`)
                    .then(status)
                    .then(res => res.json())    
                    .catch(error => {
                        return Promise.reject()
                    })
                });
        };
    }
    
    
    function status(res) {
        if (!res.ok) {
            throw new Error(res.statusText);
        }
        return res;
    }
    
    0 讨论(0)
提交回复
热议问题