提取:如果状态不正常,则拒绝承诺并捕获错误?


72

这是我要去的事情:

import 'whatwg-fetch';

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 => {
                    throw(error);
                })
            });
    };
}

function status(res) {
    if (!res.ok) {
        return Promise.reject()
    }
    return res;
}

编辑:诺言不会被拒绝,这就是我试图找出的。

我正在Redux和redux-promise-middleware中使用此访存polyfill


2
您在其中引发了异常,catch但没有catch
zerkms's

确实到达了catch(它捕获了附加到它的整个链中的所有拒绝),但是catch回调不处理任何事情-它仅抛出错误。throw用aconsole.error左右替换。
Bergi '16

浏览器死机了?那绝对不应该发生。
Bergi'7

谢谢大家,我对此有些陌生,冻结是由其他原因引起的。我认为这对我来说是个问题,因为polyfill将404视为成功响应。一旦我确定应该没问题,我就很难兑现承诺。
Vlady Veselinov

更好的东西github.com/github/fetch/issues/203#issuecomment-143347675
Usman

Answers:


176

发生网络错误时,提取承诺仅以TypeError拒绝。由于4xx和5xx响应不是网络错误,因此没有任何问题。您需要自己抛出一个错误才能使用Promise#catch

一个获取响应方便地提供的ok ,它告诉你的请求是否成功。这样的事情应该可以解决问题:

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)
});

2
我没有找到一个属性“OK”,而不是我查response.status === 200
托斯滕巴特尔

3
为什么我不能从代码中知道为什么抛出TypeError?在控制台中,我看到一种情况是“ net :: ERR_CONNECTION_TIMED_OUT”,而另一种情况中是“(blocked:mixed-content)”,我不想对两者都做出同样的反应。
迈克尔,

该解决方案将停止停止在控制台中出现错误,例如401无效请求吗?
席瓦赛

4
如果没有网络连接或服务器以例如a响应(503 Service Temp. Unavailable如果拒绝的承诺结果为a),我们如何返回自定义响应TypeError
tonix

15

感谢大家的帮助,拒绝诺言.catch()解决了我的问题:

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;
}

您也可以这样拒绝状态函数中的Promise:function status(res) { if (!res.ok) { return Promise.reject(res.statusText); } return res; } 或者实际上,您可以通过端点给出的消息来拒绝Promise 。
制表大师

或者,实际上,如果您对jsonfy响应进行响应,然后使用端点给出的消息拒绝promise,然后返回一个Promise被拒绝,并从jsonfied响应中选择属性。
钟表匠

3
.catch(error => { return Promise.reject() })似乎毫无意义。为什么抑制有用error而拒绝undefined呢?
Bergi

2
@Vivek或者您也可以只是throw undefined;。我抱怨的不是拒绝,而是忽略了error。也许整个事情应该被省略。
Bergi

1
@Vivek可能更有意义,但这不是他们所做的。undefined在正确的消息上使用代替错误仍然是一种不好的做法。
Bergi

6

对于我来说,fny的答案确实可以解决所有问题。由于fetch不会引发错误,因此我们需要自己引发/处理错误。用异步/等待发布我的解决方案。我认为这更具前瞻性和可读性

解决方案1:不引发错误,请自行处理错误

  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);
  }

在这里,如果遇到错误,我们将构建一个错误对象,普通的JS对象并返回它,缺点是我们需要在外部进行处理。如何使用:

  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

解决方案2:使用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);
  }

在这里,我们抛出并创建了我们创建的错误,因为Error ctor仅批准字符串,Im创建了普通的Error js对象,其用法为:

  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
  }

解决方案3:使用客户错误

  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);
  }

和:

class ClassError extends Error {

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

}

希望能有所帮助。


2

我只是检查了响应对象的状态:

$promise.then( function successCallback(response) {  
  console.log(response);
  if (response.status === 200) { ... }
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.