假设我有一个登录功能
login = () => {
let url = baseURL + '/user/login?_format=json';
let data = {
"name": this.state.email,
"pass": this.state.password
};
return axios({
url,
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
withCredentials: true,
credentials: 'same-origin'
})
.then(function(result) {
console.log('result:', result);
this.setState({csrfToken: result.data.csrf_token});
this.setState({logoutToken: result.data.logout_token});
return result;
})
.catch(error => console.log('error:', error));
};
然后我想在React中调用onSubmit函数,如下所示。如果函数因任何原因返回错误。在这种情况下,如何防止api.login()
的下一个功能被运行?
{api => (
<Form
onSubmit={async e => {
e.preventDefault();
await this.login();
api.login()
}}
>
<input/>
</Form>
在这种情况下,try / catch是否有意义?我已经尝试了几个选项,包括内联try catch和函数运行,无论发生什么,只要this.login();
的承诺返回结果或错误。
为什么不把api.login()
放在首次登录承诺then
回调中?
login = () => {
let url = baseURL + '/user/login?_format=json';
let data = {
"name": this.state.email,
"pass": this.state.password
};
return axios({
url,
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
withCredentials: true,
credentials: 'same-origin'
})
.then(function(result) {
console.log('result:', result);
this.setState({csrfToken: result.data.csrf_token});
this.setState({logoutToken: result.data.logout_token});
api.login() // <----- if you want to check result just wrap it in an if statement if (result) api.login()
return result;
})
.catch(error => console.log('error:', error));
};
否则你可以让login()
返回一个布尔值或truthy / falsy值然后做这样的事情(未经测试的代码):
{api => (
<Form
onSubmit={async e => {
e.preventDefault();
await this.login() && api.login()
}}
>
<input/>
</Form>
这是the answer to the previous question中提到的问题,
登录的问题在于其控制流程存在缺陷。它无法有效地捕获错误,因为它会抑制错误。
.catch(error => console.log('error:', error))
抑制错误,而不应该适当控制流量。拒绝应在消费承诺的顶层处理。即使需要在catch
中处理错误(根本不需要console.log
),也应该重新抛出。
在React中,一致地处理异步错误是一个单独的问题。需要在生命周期钩子中同步捕获和重新抛出异步错误(可能是componentDidUpdate
):
componentDidUpdate() {
if (this.state && this.state.error) {
throw this.state.error;
}
}
onSubmit = async e => {
try {
e.preventDefault();
await this.login();
api.login();
} catch (err) {
this.setState({ error: err });
}
}
render() {
...
<Form onSubmit={this.onSubmit}>
<input/>
</Form>
...
}
在componentDidUpdate
中重新抛出的错误将传播到错误边界组件或将导致异常,即demo。
可以在DRY try {...} catch (err) { this.setState({ error: err }) }
样板上引入一些额外的助手。
我认为这可能会发生,因为你只是在catch方法中运行console.log,而不是抛出错误或拒绝Promise。因此,等待的try / catch块继续运行,就好像一切正常。尝试使用Promise.reject或新的Error()抛出错误。
var catchWithoutRejection = async () => {
await console.log('hello')
console.log('running')
}
catchWithoutRejection();
// hello
// running
// Promise {<resolved>: undefined}
var catchWithRejection = async () => {
await Promise.reject("hello")
console.log('not running')
}
catchWithRejection();
// Promise {<rejected>: "hello"}