在等待完成之前调用函数

时间:2020-07-20 14:17:59

标签: javascript async-await

我正在尝试使用async / await进行某些操作,并且由于某种原因我的功能在我的等待完成之前运行,有人可以告诉我为什么吗?

(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>

4 个答案:

答案 0 :(得分:0)

函数CreatePost()不是async,它不返回Promise。这就是为什么将await放在其调用前面没有任何作用的原因。

为了使其async,使其创建并返回Promise

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

getPosts()相同。

答案 1 :(得分:0)

由于setTimeout不返回任何承诺。它不会等到CreatePost函数执行完毕。因此,将相同的内容包装在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() {
    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();

})();

答案 2 :(得分:0)

如果您想使用async,则awaitpromise

(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();
})();

答案 3 :(得分:0)

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

基本上,您将不会等待发布到列表中的帖子。这就是未显示它的原因。如果GetPosts中的间隔小于CreatePost中的间隔,则间隔将显示。 它与异步/等待无关。 由于您没有返回Promise,因此对CreatePost的调用首先不异步。第二件事是setTimeout不会被阻塞,因此在之后运行的每个代码基本上都可以在调用回调之前完成。

要使CreatePost真正异步,只需查看@axiac Function is being called before await finishes的答案 注意:setTimeout仍然是非阻塞的,代码将无法按预期工作。如果这不只是锻炼,我会说摆脱setTimeouts。