javascript - 对象有值但说大小为 0 javascript

标签 javascript

我创建一个对象并向其添加属性和值。但是,当我尝试遍历键时,它说我的大小为 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);

我的输出如下(最后一行的数组为空):

Output

最佳答案

您正在使用异步函数添加到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';

您将看到 objfoo 属性是 '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/

相关文章:

javascript - Jquery添加输入字段和日期选择器

javascript - 如何换行或向此 Javascript 函数添加 HTML?

javascript - JavaScript 中图像数组 "document.write()"的问题

javascript - PHP更改个人资料图片

javascript - 通过 javascript 设置 Shopify 选项选择器/更改所选变体的值

javascript - 在 JQuery、javascript 中解析 JSON 响应时出错

javascript - 如何在 React 组件中使用 exif-js?

javascript - JQuery 警报不适用于 onkeyup 事件

javascript - 使用 jquery 从 .cshtml 页面调用 Controller 操作

javascript - 在菜单中滑动以隐藏然后点击链接