Javascript Fetch:如果状态不正常,是否拒绝承诺并捕获错误?

Javascript Fetch:如果状态不正常,是否拒绝承诺并捕获错误?,javascript,redux,fetch-api,Javascript,Redux,Fetch Api,下面是我要说的: import 'whatwg-fetch'; function fetchVehicle(id) { return dispatch => { return dispatch({ type: 'FETCH_VEHICLE', payload: fetch(`http://swapi.co/api/vehicles/${id}/`) .then(status)

下面是我要说的:

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中使用此选项。

承诺在出现网络错误时,仅使用TypeError拒绝。因为4xx和5xx响应不是网络错误,所以没有什么可捕获的。您需要自己抛出一个错误才能使用
Promise\catch

A方便地提供了,它告诉您请求是否成功。像这样的事情应该可以做到:

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

感谢大家的帮助,拒绝了
中的承诺。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.then( function successCallback(response) {  
  console.log(response);
  if (response.status === 200) { ... }
});
对我来说, fny的回答真的很全面。因为fetch不是抛出错误,所以我们需要自己抛出/处理错误。 使用async/await发布我的解决方案。我认为它更具前瞻性和可读性

解决方案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);
  }
这里我们抛出了我们创建的错误,因为错误只批准字符串,我创建了纯错误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);
  }
以及:

希望有帮助。

2021打字稿答案 我要做的是编写一个
fetch
包装器,它接受一个泛型,如果
响应
ok
它将自动
.json()
并键入assert结果,否则包装器抛出
响应

export const fetcher=async(输入:RequestInfo,init?:RequestInit)=>{
const response=等待获取(输入,初始化);
如果(!response.ok){
投掷反应;
}
返回response.json()作为承诺;
};
然后我将捕获错误并检查它们是否是响应的
实例。这样,TypeScript就知道
错误
具有
响应
属性,例如
状态
状态文本
正文
标题
等。我可以为每个
4xx
5xx
状态代码应用自定义消息

试试看{
返回等待获取程序(“http://localhost:8080/login", {
方法:“张贴”,
标题:{
接受:“应用程序/json”,
“内容类型”:“应用程序/json”,
},
正文:JSON.stringify({email:user@example.com,密码:“passw0rd”}),
});
}捕获(错误){
if(响应的错误实例){
开关(错误状态){
案例401:
抛出新错误(“无效登录凭据”);
/* ... */
违约:
抛出新错误(`发生未知服务器错误:${Error.statusText}`);
}
}
抛出新错误(`Something出错:${Error.message | | Error}`);
}
如果出现类似网络错误的情况,则可以在响应的
实例之外捕获,并使用更通用的消息进行检查,即

抛出新错误(`Something出错:${Error.message | | Error}`);

以下
使用用户名和密码登录的示例演示了如何:

  • 检查
    响应。确定
  • 如果不正常,则拒绝
    ,而不是抛出错误
  • 进一步处理来自服务器的任何错误提示,例如验证问题

  • 您在
    catch
    中抛出异常,但不
    catch
    它。它确实到达
    catch
    (它捕获它所连接的整个链中的所有拒绝),但是
    catch
    回调不处理任何事情-它只会重新返回错误。用
    控制台替换
    抛出
    。错误
    左右。浏览器冻结?这绝对不应该发生。谢谢各位,我对这有点陌生,冰冻是由其他原因造成的。我认为这对我来说是一个问题,因为它将404视为一个成功的响应。我在拒绝这个承诺时遇到了一些麻烦,一旦我发现它应该是好的。更优秀的github.com/github/fetch/issues/203#issuecomment-14347675我没有找到属性“ok”,而是检查了response.status==200。为什么我不能从代码中判断抛出TypeError的原因?在控制台中,我看到一个例子是“net::ERR\u CONNECTION\u TIMED\u OUT”,但在另一个例子中是“(blocked:mixed content)”我不想对两者都做出相同的响应。此解决方案是否会停止在控制台中获取错误,例如401无效请求?当没有网络连接或服务器响应(例如,
    503 Service Temp)时,我们如何返回自定义响应。不可用
    如果拒绝承诺的结果是
    类型错误
    ?如何读取捕获中的JSON?我从捕获块中需要的BE发送附加数据您也可以拒绝状态函数的承诺,如下所示:
    function status(res){if(!res.ok){return Promise.reject(res.statusText);}return res;}
    或者实际上,您可以使用端点提供的消息拒绝承诺。或者,如果您对该响应进行jsonfy,然后使用从jsonfied响应中选择的属性返回拒绝的承诺,您也可以使用端点提供的消息拒绝承诺。这
    .catch(错误=>{返回承诺。拒绝()})
    似乎毫无意义。为什么要抑制有用的
    错误
    而用
    未定义的
    来拒绝呢?@Vivek或者你也可以同样地
    抛出未定义的;
    。我抱怨的不是拒绝,而是忽略了
    错误
    。不过可能整个事情都应该忽略。@Vivek这可能会让我更痛苦e是有意义的,但这不是他们所做的。同样使用
    undefined
    代替带有正确消息的错误是s
    class ClassError extends Error {
    
      constructor(message = 'Something went wrong', data = '', code = '') {
        super();
        this.message = message;
        this.data = data;
        this.code = code;
      }
    
    }
    
    login() {
      const url = "https://example.com/api/users/login";
      const headers = {
        Accept: "application/json",
        "Content-Type": "application/json",
      };
      fetch(url, {
        method: "POST",
        headers,
        body: JSON.stringify({
          email: this.username,
          password: this.password,
        }),
      })
        .then((response) => {
          // 1. check response.ok
          if (response.ok) {
            return response.json();
          }
          return Promise.reject(response); // 2. reject instead of throw
        })
        .then((json) => {
          // all good, token is ready
          this.store.commit("token", json.access_token);
        })
        .catch((response) => {
          console.log(response.status, response.statusText);
          // 3. get error messages, if any
          response.json().then((json: any) => {
            console.log(json);
          })
        });
    },