我完全承认我现在对反应性本地非常陌生,所以我预计这是一个简单的答案,也是一个潜在的愚蠢问题:)实际上,这可能不是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 });
};
}
目标是仅加载来自异步的数据并将其转储到列表中。相当基本的看来,对吗?不幸的是,我无法工作:列表为空。
现在,要介绍愚蠢的事物:是的,确实有数据存储,是的,它是正确的(我知道这一点列表如预期)。
实际上,我知道问题是什么:是setState()调用在键完成之前执行。我知道这一点,因为如果我替换setState()调用:
setTimeout(function() {
this.setState({ listData : data });
}.bind(this), 1000);
...然后突然我的列表按预期填充(我也可以在其中扔一些console.log()s,然后看到一个接一个键的foreach()呼叫实际上是在键内执行的。foreach())。我也知道显然是在调用json.parse()之前等待getItem()呼叫,否则这根本不起作用。
换句话说:我知道这是由此代码的异步性质引起的。我似乎无法弄清楚的是如何正确编写以避免这种情况。
我正在看它,我在想:"好吧,keys.foreach()是一个阻止呼叫,所以在setState()呼叫之前,它怎么可能无法完成,尤其是考虑到键上的异步用法。foreach()回调和在getItem()呼叫内部的等待用法?
所以,这似乎是一个基本的JavaScript问题,但我似乎无法解决...但是另一方面,我不确定我是否想以某种方式进行此操作从根本上讲,我不应该在RN土地上,这也许是真正的问题。
请注意,由于流过应用程序的流动,数据必须从异步部件中动态拉动(在另一个屏幕上添加),因此在我看来,尝试将其加载到componentdidmount()中是有道理的,我是只是挂断了所涉及的呼叫的异步性。
有什么建议?
谢谢!
编辑:我还应该提到,我知道我可以解决的一种方法就是完全删除异步性质:而不是存储单个数据项,而是将所有内容存储在Asyncstorage中的单个对象中。然后,我可以读取一个项目,这是一个数组(或包含一个数组),然后唯一的异步部分是getItem()调用,但是我可以使用它的回调版本并使其以这种方式工作。而且我根本不反对这种方法,但是在这一点上,我真的很想理解我在做什么错的原因,除了学习某些东西外,因为这似乎应该有效:)
<</p> keys.forEach
在其自己的范围中执行代码(在其自己的回调函数中),并破坏您的async / await
对。
而是这样做:
for (let inKey of keys) {
let obj = await AsyncStorage.getItem(inKey);
obj = JSON.parse(obj);
data.push(obj);
}
如果您真的想要forEach
,则必须编写自己的版本来返回Promise
,因此可以在其上挂钩await
,例如:
await keys.awaitableForEach(async function(inKey) {