我创建一个对象并向其添加属性和值。但是,当我尝试遍历键时,它说我的大小为 0。
let hash = {};
this.props.user.user.following.forEach(async topicId => {
await API.graphql(graphqlOperation(queries.getTopic, {id: topicId})).then(data => {
if(data) {
const tweetId = data.data.getTopic.post.id;
if(!hash[tweetId]){
let post = data.data.getTopic.post;
post.topics = [{
id: data.data.getTopic.id,
name: data.data.getTopic.name
}]
hash[tweetId] = post;
} else {
console.log("Found tweet. Appending to topics array.");
let post = hash[tweetId];
let topicsArr = post.topics;
topicsArr.push({
id: data.data.getTopic.id,
name: data.data.getTopic.name
})
post.topics = topicsArr;
hash[tweetId] = post;
}
}})
});
console.log("Hash: ", hash);
console.log("Map size: ", Object.keys(hash).length);
let tweets = [];
for(var key in hash) {
tweets.push(hash[key]);
}
console.log("Tweets to go into state: ", tweets);
我的输出如下(最后一行的数组为空):
最佳答案
您正在使用异步函数添加到hash
对象。
因此,forEach
的每次运行都是异步完成的,并且其余代码的评估继续进行。您使用数据的 block 在异步函数全部完成之前运行。
您应该在同一个异步 block 中同时拥有获取 API 调用的数据的代码和处理来自 API 调用的数据的代码,因为当您想到这一点时,代码块可以“t 依赖于异步代码,而本身并不是异步的。
您可能想要等待在该循环中执行的所有 API 调用。为此,您可以使用 Array.prototype.map()
和 Promise.all()
.
const tweets = async () => {
let hash = {};
await Promise.all(this.props.user.user.following.map(async topicID => {
const data = await API.graphql(graphqlOperation(queries.getTopic, { id: topicID }));
// No need to use .then(), since we're awaiting anyways
if (data) {
const tweedID = data.data.getTopic.post.id;
if (!hash[tweetID]) {
let post = data.data.getTopic.post;
post.topics = [{
id: data.data.getTopic.id,
name: data.data.getTopic.name
}]
hash[tweedID] = post;
} else {
console.log("Found tweet. Appending to topics array.");
let post = hash[tweedID];
let topicsArr = post.topics;
topicsArr.push({
id: data.data.getTopic.id,
name: data.data.getTopic.name
});
post.topics = topicsArr;
hash[tweedID] = post;
}
}
}));
console.log("Hash: ", hash);
console.log("Map size: ", Object.keys(hash).length);
let tweets = [];
for (const key in hash) {
tweets.push(hash[key]);
}
console.log("Tweets to go into state: ", tweets);
}
tweets();
// Or, put the whole thing in brackets and call it immediately:
(async () => {
// ...
})();
<小时/>
您看到记录的对象具有值的原因是因为开发控制台的一项功能可以实时刷新对象的属性,因此它们将不再反射(reflect)记录时的状态,而是显示它们的当前值。
考虑以下示例:
const obj = {};
console.log(obj);
obj.foo = 'bar';
您将看到 obj
的 foo
属性是 'bar'
,即使它是未定义
code> 当 console.log
实际运行时。如@epascarello在评论中指出,你可以通过小蓝色的 [i]
来判断你的浏览器何时执行了此操作。如果将鼠标悬停在其上,您会看到它显示“此值刚刚被评估”。
为了避免这种行为,请在记录之前对对象进行JSON.stringify
:
const obj = {}
console.log(JSON.stringify(obj))
obj.foo = 'bar'
正如您所料,这将记录 {}
,因为它将其转换为字符串并吐出该文本,而不是对 obj
的引用。
查看更多here .
关于javascript - 对象有值但说大小为 0 javascript,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58962487/