简体   繁体   中英

Function is being called before await finishes

I was trying out some things with async/await and for some reason my function runs before my await is finished, can someone tell me why?

 (function() { var posts = [{ title: "Post 1", body: "This is post 1" }, { title: "Post 2", body: "This is post 2" }, { title: "Post 3", body: "This is post 3" } ]; function GetPosts() { setTimeout(() => { let output = ''; posts.forEach((post, index) => { output += `<li>${post.title}</li>`; }); document.body.innerHTML = output; }, 1000); } function CreatePost(post) { setTimeout(() => { posts.push(post); }, 4000); } async function init() { await CreatePost({ title: "Post 4", body: "This is post 4" }); GetPosts(); } init(); })();
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

The function CreatePost() is not async , it does not return a Promise . This is why putting await in front of its call does not have any effect.

In order to make it async let it create and return a Promise :

  async function CreatePost(post) {
    return new Promise((resolve) => {
      setTimeout(() => {
        posts.push(post);
        resolve();
      }, 4000);
    });
  }

The same for getPosts() .

Since setTimeout doesn't return any promise. It'll not wait till CreatePost function gets executed. So wrapping the same thing inside a Promise will help to give the output that you are looking for.

 (function() { var posts = [{ title: "Post 1", body: "This is post 1" }, { title: "Post 2", body: "This is post 2" }, { title: "Post 3", body: "This is post 3" } ]; function GetPosts() { setTimeout(() => { let output = ''; posts.forEach((post, index) => { output += `<li>${post.title}</li>`; }); document.body.innerHTML = output; }, 1000); } //Wrap this with a new promise function CreatePost(post) { return new Promise((resolve, reject) => { setTimeout(() => { posts.push(post); resolve(); }, 3000); }) } async function init() { await CreatePost({ title: "Post 4", body: "This is post 4" }); GetPosts(); } init(); })();

If you want to use async , await is promise

 (function () { var posts = [{ title: "Post 1", body: "This is post 1" }, { title: "Post 2", body: "This is post 2" }, { title: "Post 3", body: "This is post 3" } ]; function GetPosts() { return new Promise(resolve => { setTimeout(() => { let output = ''; posts.forEach((post, index) => { output += `<li>${post.title}</li>`; resolve('success'); }); document.body.innerHTML = output; }, 1000); }) } function CreatePost(post) { return new Promise((resolve) => { setTimeout(() => { posts.push(post); resolve('success') }, 4000); }) } async function init() { const a = await CreatePost({ title: "Post 4", body: "This is post 4" }); const b = await GetPosts(); return b } init(); })();

function CreatePost(post) {
  //setTimeout is non-blocking
  setTimeout(() => {
    posts.push(post);
  }, 4000);
}

You will basically not wait for the post to be pushed to the list. That is the reason it is not shown. if the interval in GetPosts was smaller than the on in CreatePost than it would display. It has nothing to do with async/await. The call to CreatePost is first of all not async because you are not returning a Promise . The Second thing is that setTimeout will not block, so every code that runs after can basically be done before the callback will be called.

To make CreatePost really async just look at the answer of @axiac Function is being called before await finishes Note: setTimeout is still non-blocking and the code won't work as expected. If this wasn't just exercise, I would say get rid of the setTimeouts.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM