0

I just started to try asynchronous JS with setTimeout() function. I hardcoded two objects in an JS Array and added one with a method that runs in 3S delay. I've written another method that prints the array (both HTML Response and Console.log). Printing to response does seem to work fine, that is till posts.push(post) called, only two objects get written to HTML Response.

But sometimes console.log() prints 3 objects, either before "begin addpost" or sometimes even before addPost() invocation while addPost is called only after 5000ms. Not sure what am I doing wrong here. Can someone help?

const posts = [{
    body: "I am Post One",
    title: "Post One"
  },
  {
    body: "I am post two",
    title: "Post Two"
  }
]

function addPost(post) {
  setTimeout(function() {
    console.log("begin addpost");
    let output = "<p> ";
    posts.forEach(function(post) {
      output += (post.body + "<br/>");
    });

    output += "</p>";
    document.body.innerHTML = output;

    posts.push(post);

    console.log("end addpost");

  }, 5000);
}

function getPosts() {
  setTimeout(function() {
    console.log("begin getpost");
    console.log(posts);
    console.log("end getpost");
  }, 1000);
}

console.log(posts);
addPost({
  body: "I am  post Three",
  title: "Post Three"
});
getPosts();
Andy
  • 61,948
  • 13
  • 68
  • 95
Mail
  • 314
  • 1
  • 2
  • 9
  • _"But sometimes console.log() prints 3 objects"_ - Use `console.log(JSON.stringify(posts))` instead. If this "fixes" your problem (ignore the Chrome reference if you're not using Chrome) -> [Is Chrome's JavaScript console lazy about evaluating arrays?](https://stackoverflow.com/questions/4057440/is-chromes-javascript-console-lazy-about-evaluating-arrays) – Andreas Aug 28 '21 at 11:39
  • Even without JSON.stringify() the behaviour is not consistent. I sometimes get 3 objects before addPosts() or posts.push(post) and sometimes 2. What's different about JSON.stringify here? Checked the reference you shared and an answer has it, but couldn't reason it. Is the behaviour I am seeing is due to some kind of cache? Sometimes changing the value in array yields different results. – Mail Aug 28 '21 at 11:53
  • 1
    _"Even without JSON.stringify() the behaviour is not consistent."_ - You're not using `JSON.stringify()`. So how do you know that the behavior is the same with and w/o `JSON.stringify()`? If you expand a logged element, the "console" re-evaluates the state of that object, hence the "output" can be different to what one would expect. That's what the linked question explains. – Andreas Aug 28 '21 at 11:56
  • Andreas, Thanks much. I was using JSON.stringify locally but couldn't find why the object is behaving randomly. After hours of trying around, finally understood that console reevaluates when expanding an object. So the weird stuff here was I was sometimes expanding objects after it was printed and the object was updated and sometimes before updating. I also guess once you expand and object, and shrink it and if the object gets updated, the object still retain the old value. Now it makes total sense. Thanks much! – Mail Aug 28 '21 at 12:01

1 Answers1

-1

I think this line was the reason why your console print 3 objects instead of two.

posts.push(post);

This is caused when you don't re-initialize the posts object. (Which actually requires you to reload). I'm not sure this is the real issue which you are facing with but after few minutes of reading your code, I don't see any other possibilities.

Furthermore, if you're trying asynchronous with JavaScript, this may be a shorter and cleaner way to do what you want:

const posts = [{
    body: "I am Post One",
    title: "Post One"
  },
  {
    body: "I am post two",
    title: "Post Two"
  }
]
async function wait(ms) {
    // please do read more about Promise & arrow function to understand the syntax.
    return new Promise(_ => setTimeout(_, ms));
}

const getPost = async () => {
    await wait(1000);
    console.log("begin getpost");
    console.log(posts);
    console.log("end getpost");
}

const printPost = async () => {
    await wait(4000);
    console.log("begin addpost");
    let output = "<p> ";
    posts.forEach(function(post) {
      output += (post.body + "<br/>");
    });

    output += "</p>";
    document.body.innerHTML = output;
    console.log("end addpost");
}

(async () => {
    getPost();
    printPost();
})();

This will be a little bit more readable. Have fun with JavaScript!

MonokaiJs
  • 3
  • 3
  • Thanks for the answer but my question is not about better-way of doing async or readability. – Mail Aug 28 '21 at 11:54