Fra*_*tti 6 javascript async-await reactjs react-native react-native-flatlist
我完全承认我现在对Reactive Native很新,所以我预计这是一个简单的答案和一个潜在的愚蠢问题:)事实上,这可能不是RN问题本身,我将在下面解释.
我所拥有的是以下代码:
class MyScreen extends React.Component {
constructor(inProps) {
super(inProps);
this.state = { listData : [ ] };
}
render() { return (
<View>
<FlatList data={ this.state.listData }
renderItem={ ({item}) =>
<Text>{item.firstName} {item.lastName}</Text>
}
/>
</View>
); }
async componentDidMount() {
const data = [ ];
let keys = await AsyncStorage.getAllKeys();
keys.forEach(async function(inKey) {
let obj = await AsyncStorage.getItem(inKey);
obj = JSON.parse(obj);
data.push(obj);
});
this.setState({ listData : data });
};
}
Run Code Online (Sandbox Code Playgroud)
目标只是从AsyncStorage加载数据并将其转储到列表中.看起来相当基本,对吧?不幸的是,我无法让它工作:列表是空的.
现在,为了掩盖愚蠢的事情:是的,确实存储了数据,是的,它是正确的形式(我知道这是因为如果我只是抓住一个SPECIFIC项目并将其推送到数据中,那么它会按预期显示在列表中).
实际上,我知道问题是什么:它是在keys.forEach()调用完成之前执行的setState()调用.我知道这个,因为如果我用这个替换setState()调用:
setTimeout(function() {
this.setState({ listData : data });
}.bind(this), 1000);
Run Code Online (Sandbox Code Playgroud)
...然后突然我的列表按预期填充(我也可以在其中抛出一些console.log()并看到keys.forEach()调用之后的那个实际上在keys.forEach()内的那些执行之前执行).我也知道,显然getItem()调用在调用JSON.parse()之前等待,否则这根本不起作用.
换句话说:我知道这是由此代码的异步性质引起的.我似乎无法弄清楚的是如何正确地编写以避免这种情况.
我正在考虑它,我在想"好吧,keys.forEach()是一个阻塞调用,所以怎么可能在setState()调用之前没有完成,ESPECIALLY给出了keys.forEach()上的异步使用回调和等待内部getItem()调用的使用?"...我唯一的想法是在keys.forEach()调用前放弃异步,但这没有任何区别.
所以,它本质上似乎是一个基本的JavaScript问题,但我似乎无法解决它...但另一方面,我不确定我是否试图以一种我从根本上的方式做到这一点不应该在RN土地上,也许这是真正的问题.
请注意,由于流经应用程序的流量,数据必须从AsyncStorage动态提取(添加在另一个屏幕上完成),所以在我看来尝试在componentDidMount()中加载它是有道理的,我只是挂了与所涉及的调用的异步性质有关.
有什么建议?
谢谢!
编辑:我还应该提一下,我知道我可以解决的一种方法是完全删除异步性质:而不是存储单个数据项,而是将所有内容存储在AsyncStorage中的单个对象中.然后我可以读取ONE项,它将是一个数组(或将包含一个数组),然后唯一的异步部分是getItem()调用,但我可以使用它的回调版本并使其工作方式..我完全不反对这种方法,但是在这一点上我真的想要明白我做错了,如果没有其他原因而不是学习一些东西,因为这似乎应该工作:)
keys.forEach在它自己的范围内(在它自己的回调函数中)执行代码,这会破坏你的async / await配对。
改为这样做:
for (let inKey of keys) {
let obj = await AsyncStorage.getItem(inKey);
obj = JSON.parse(obj);
data.push(obj);
}
Run Code Online (Sandbox Code Playgroud)
如果你真的想要forEach,你必须编写自己的返回版本Promise,这样你就可以使用await它,例如:
await keys.awaitableForEach(async function(inKey) {
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1407 次 |
| 最近记录: |