爱玩的鸡蛋面 · react函数式组件 async ...· 5 天前 · |
个性的红酒 · 【译】如何在React hooks ...· 5 天前 · |
稳重的芹菜 · django:restframework定义 ...· 4 天前 · |
要出家的火车 · Django+rest_framework ...· 4 天前 · |
豪情万千的回锅肉 · 三分钟了解 Python3 的异步 Web ...· 4 天前 · |
乐观的针织衫 · C++ 打印变量地址 - ...· 2 周前 · |
不开心的盒饭 · 万顺叫车赴美上市,去年收入规模高达50亿元_ ...· 3 月前 · |
发怒的卤蛋 · ListView.View 属性 ...· 5 月前 · |
追风的毛衣 · (转)吐血收集的.net组件和控件 - ...· 1 年前 · |
爱吹牛的香烟 · python - How to fix ...· 1 年前 · |
使用
componentDidMount()
作为异步函数是否是反应本地的良好实践,还是我应该避免它?
当组件挂载时,我需要从
AsyncStorage
获得一些信息,但我所知道的唯一可能的方法是使
componentDidMount()
函数异步。
async componentDidMount() {
let auth = await this.getAuth();
if (auth)
this.checkAuth(auth);
}
这个问题有什么问题吗?还有其他解决办法吗?
发布于 2017-12-25 17:46:58
让我们首先指出不同之处,并确定它是如何引起麻烦的。
下面是异步和“同步”
componentDidMount()
生命周期方法的代码:
// This is typescript code
componentDidMount(): void { /* do something */ }
async componentDidMount(): Promise<void> {
/* do something */
/* You can use "await" here */
}
通过查看代码,我可以指出以下不同之处:
async
关键字:在类型记录中,这只是一个代码标记。它做了两件事:
Promise<void>
而不是
void
。如果您显式地指定返回类型为不承诺(例如:无效),类型记录将向您吐出一个错误。
await
关键字。
void
更改为
Promise<void>
async someMethod(): Promise<void> { await componentDidMount(); }
await
关键字,并暂时暂停其执行。类似于这样:异步componentDidMount():承诺{ const用户=等待axios.get(“
http://localhost:9001/users"
”);const问题=等待axios.get(“
http://localhost:9001/questions"
”);//睡眠10秒等待新的承诺(resolve => { setTimeout(resolve,10000);});//这一行代码将在10+秒this.setState({ users,问题})之后执行;返回Promise.resolve();}
,现在,他们怎么能制造麻烦呢?
async
关键字是绝对无害的。
componentDidMount()
方法的任何情况,因此返回类型
Promise<void>
也是无害的。
调用具有
Promise<void>
返回类型而不带
await
关键字的方法与调用具有
void
返回类型的方法没有任何区别。
componentDidMount()
之后没有生命周期方法,延迟执行它似乎是非常安全的。但还是有个问题。
比如说,上面的
this.setState({users, questions});
将在10秒后执行。在拖延时间的中间,另一个..。
this.setState({users: newerUsers, questions: newerQuestions});
..。已成功执行并更新了DOM。结果对用户是可见的。时钟继续滴答作响,10秒过去了。延迟的
this.setState(...)
然后将执行,DOM将再次更新,这一时间与老用户和老问题。结果对用户也是可见的。
=> --使用
async
和
componentDidMount()
方法是非常安全的(我不确定大约100%)。我是它的忠实粉丝,到目前为止,我还没有遇到任何让我头疼的问题。
发布于 2019-06-28 03:08:46
更新2020年4月: 问题似乎在最新的反应16.13.1中得到了解决,见 这个沙箱例子 。感谢@abernier指出这一点。
我做了一些研究,并发现了一个重要的区别: React不会处理来自异步生命周期方法的错误。
所以,如果你写这样的东西:
componentDidMount()
throw new Error('I crashed!');
}
然后您的错误将被 误差边界 捕获,您可以处理它并显示一条优美的消息。
如果我们像这样修改代码:
async componentDidMount()
throw new Error('I crashed!');
}
这相当于:
componentDidMount()
return Promise.reject(new Error('I crashed!'));
}
然后,您的错误将被默默吞下。为你感到羞耻,反应..。
那么,我们如何处理错误比呢?唯一的办法似乎是这样明确地抓到:
async componentDidMount()
await myAsyncFunction();
catch(error)
//...
}
或者像这样:
componentDidMount()
myAsyncFunction()
.catch(()=>
//...
}
如果我们仍然希望我们的错误达到错误边界,我可以考虑以下技巧:
render
方法抛出它。
示例:
class BuggyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { error: null };
buggyAsyncfunction() { return Promise.reject(new Error('I crashed async!'));}
async componentDidMount() {
await this.buggyAsyncfunction();
catch(error)
this.setState({error: error});
render() {
if(this.state.error)
throw this.state.error;
return <h1>I am OK</h1>;