Vla*_*nov 38 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)
.then(res => res.json())
.catch(error => {
throw(error);
})
});
};
}
function status(res) {
if (!res.ok) {
return Promise.reject()
}
return res;
}
Run Code Online (Sandbox Code Playgroud)
编辑:承诺不会被拒绝,这就是我想要弄清楚的.
我在Redux中使用这个fetch polyfill和redux-promise-middleware.
fny*_*fny 98
当发生网络错误时,获取 promise只会拒绝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)
});
Run Code Online (Sandbox Code Playgroud)
Jar*_*rod 19
我所做的是编写一个fetch采用泛型的包装器,如果是,response它将ok自动.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>;
};
Run Code Online (Sandbox Code Playgroud)
然后我会捕获错误并检查它们是否是instanceof Response. 这样,TypeScript 就知道它error具有Response诸如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}`);
}
Run Code Online (Sandbox Code Playgroud)
instanceof Response如果发生网络错误之类的情况,可以使用更通用的消息在检查之外捕获它,即
throw new Error(`Something went wrong: ${error.message || error}`);
Run Code Online (Sandbox Code Playgroud)
Tom*_*mri 16
对我来说,fny 的答案真的解决了一切。由于 fetch 不会抛出错误,我们需要自己抛出/处理错误。使用 async/await 发布我的解决方案。我认为它更严格和可读
解决方案一:不抛出错误,自己处理错误
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);
}
Run Code Online (Sandbox Code Playgroud)
这里如果我们得到一个错误,我们正在构建一个错误对象,一个普通的 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
Run Code Online (Sandbox Code Playgroud)
解决方案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);
}
Run Code Online (Sandbox Code Playgroud)
这里我们抛出我们创建的错误,因为 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
}
Run Code Online (Sandbox Code Playgroud)
解决方案 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);
}
Run Code Online (Sandbox Code Playgroud)
和:
class ClassError extends Error {
constructor(message = 'Something went wrong', data = '', code = '') {
super();
this.message = message;
this.data = data;
this.code = code;
}
}
Run Code Online (Sandbox Code Playgroud)
希望它有所帮助。
感谢大家的帮助,拒绝承诺.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;
}
Run Code Online (Sandbox Code Playgroud)
以下login with username and password示例显示了如何:
response.okreject 如果不正常,而不是抛出错误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);
})
});
},
Run Code Online (Sandbox Code Playgroud)
@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) })
})
}
Run Code Online (Sandbox Code Playgroud)
现在,该方法将拾取每个错误和非正常返回.catch:
my_fetch(url, args)
.then((response) => {
// Do something with the response
})
.catch((error) => {
// Do something with the error
})
Run Code Online (Sandbox Code Playgroud)
另一个(较短的)版本与大多数答案产生共鸣:
fetch(url)
.then(response => response.ok
? response.json()
: Promise.reject(response)) //throw if not 200-OK
.then(json => doStuff(json)) //all good
.catch(response => handleError(response)) //handle errors
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
49673 次 |
| 最近记录: |