取回: 拒绝承诺,并捕获错误,如果状态不好?

我是这么打算的:

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 中。

314966 次浏览

Fetch 承诺只在发生网络错误时使用 TypeError 拒绝。因为4xx 和5xx 响应不是网络错误,所以没有什么可捕捉的。要使用 Promise#catch,您需要自己抛出一个错误。

一个 获取响应很方便地提供一个 ok,它会告诉你请求是否成功:

fetch(url).then((response) => {
if (response.ok) {
return response.json();
}
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) { ... }
});

对我来说, 因为提取不是抛出错误,所以我们需要自己抛出/处理错误。 使用异步/等待发布我的解决方案。我认为它更加直观和可读

解决方案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);
}

在这里,我们抛出和错误,我们创建,因为错误 ctor 只批准字符串,进口创建普通的 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;
}


}

希望有帮助。

2021字体解答

我所做的是编写一个 fetch包装器,它采用一个泛型,如果 responseok,它将自动 .json()并键入断言结果,否则包装器将抛出 response

export const fetcher = async <T>(input: RequestInfo, init?: RequestInit) => {
const response = await fetch(input, init);


if (!response.ok) {
throw response;
}


return response.json() as Promise<T>;
};

然后我会抓住错误,并检查他们是否是一个 instanceof Response。这样 TypeScript 知道 errorResponse属性,比如 status statusText body headers等等,我可以为每个 4xx 5xx状态码应用一个自定义消息。

try {
return await fetcher<LoginResponse>("http://localhost:8080/login", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({ email: "user@example.com", password: "passw0rd" }),
});
} catch (error) {
if (error instanceof Response) {
switch (error.status) {
case 401:
throw new Error("Invalid login credentials");
/* ... */
default:
throw new Error(`Unknown server error occured: ${error.statusText}`);
}
}
throw new Error(`Something went wrong: ${error.message || error}`);
}

如果发生类似网络错误的情况,它可以在 instanceof Response检查之外通过更通用的消息(即。

throw new Error(`Something went wrong: ${error.message || error}`);

下面的 login with username and password示例演示如何:

  1. 检查 response.ok
  2. 如果 reject不行,则抛出一个错误
  3. 进一步处理来自服务器的任何错误提示,例如验证问题
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);
})
});
},


@ fny (公认的答案)的答案对我不起作用。throw new Error()没有被 .catch发现。我的解决方案是用一个构建新承诺的函数来包装 fetch:


function my_fetch(url, args) {
return new Promise((resolve, reject) => {
fetch(url, args)
.then((response) => {
response.text().then((body) => {
if (response.ok) {
resolve(body)
} else {
reject(body)
}
})
})
.catch((error) => { reject(error) })
})
}

现在,每个错误和不确定的返回值都会被 .catch方法识别出来:

my_fetch(url, args)
.then((response) => {
// Do something with the response
})
.catch((error) => {
// Do something with the error
})

希望这对我有帮助 抛出错误不工作

function handleErrors(response) {
if (!response.ok) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject({
status: response.status,
statusText: response.statusText,
});
}, 0);
});
}
return response.json();
}


function clickHandler(event) {
const textInput = input.value;
let output;
fetch(`${URL}${encodeURI(textInput)}`)
.then(handleErrors)
.then((json) => {
output = json.contents.translated;
console.log(output);
outputDiv.innerHTML = "<p>" + output + "</p>";
})
.catch((error) => alert(error.statusText));


}

我对所提出的任何解决方案都不满意,所以我尝试了一下 获取 API,以找到一种同时处理成功响应和错误响应的方法。

计划是得到 {status: XXX, message: 'a message'}格式作为结果在这两种情况下。

注意: 成功响应可以包含一个空主体。在这种情况下,我们回退并使用 Response.statusResponse.statusText来填充结果响应对象。

fetch(url)
.then(handleResponse)
.then((responseJson) => {
// Do something with the response
})
.catch((error) => {
console.log(error)
});


export const handleResponse = (res) => {
if (!res.ok) {
return res
.text()
.then(result => JSON.parse(result))
.then(result => Promise.reject({ status: result.status, message: result.message }));
}
return res
.json()
.then(result => Promise.resolve(result))
.catch(() => Promise.resolve({ status: res.status, message: res.statusText }));
};
function handleErrors(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response;
}
fetch("https://example.com/api/users")
.then(handleErrors)
.then(response => console.log("ok") )
.catch(error => console.log(error) );