JavaScript承诺.then和setTimeout排序

时间:2017-01-24 11:03:31

标签: javascript promise



getAllUsers(): void {
    this.allUsers = this.userService.getUsers()
      .then(res => this.allUsers = res)
      .then(() => setTimeout( () =>
      this.allUsers.forEach( user => console.log(user)), 2000
      ))
      .then(() => setTimeout(this.restOfInit(), 4000))
      .catch((error) => console.log(error)));
    // console.log(this.allUsers[0]);
    // setTimeout(() =>     console.log(this.allUsers[0]), 3000);
}




在附加的代码段中,我希望所有用户的日志记录都发生在restOfInit函数之前,因为超时之间的差异为2秒。但是,实际发生的是首先运行restOfInit,将字符串记录到控制台,然后所有用户都登录到控制台。为什么会这样?

2 个答案:

答案 0 :(得分:0)

两件事:

1)传递给setTimeout()的函数在大约指定的毫秒数内异步执行。你很可能意识到这一点。但是,setTimeout()的调用(几乎立即)返回,而不考虑指定的时间。

2)您希望传递this.restOfInit而不是this.restOfInit()。前者将函数传递给setTimeout()。后者调用没有参数的函数,并将返回值(可能是undefined)传递给setTimeout()。

<强> tldr;

.then(() => setTimeout(this.restOfInit(), 4000)) // Change this line

.then(() => setTimeout(this.restOfInit, 4000))  // to this

答案 1 :(得分:0)

正如@fvgs正确陈述的那样,你看到的触发顺序的问题在于立即调用this.restOfInit - 它的返回值传递给setTimeout而不是函数本身。

然而,在这里使用超时会违背承诺。 Promise应该允许您精确地安排订单,并且将尽可能快地执行,而不是保证等待期,无论您的用户请求有多快。您实际上根本不需要链接,因为只有第一个回调需要分辨率值。这样安排会容易得多......

    getAllUsers(): void {
      this.userService.getUsers()
        .then(res => {
          this.allUsers = res
          this.allUsers.forEach(user => console.log(user))
          this.restOfInit()
        })
        .catch((error) => console.log(error)));
    }

另外注意 - 分配this.allUsers = this.userService.getUsers()链将是一个承诺,但是在回调中你分配this.allUsers = res,它的外观将是一个数组。我怀疑这可能是你使用setTimeout的原因,因为它可能会在你不期望的时候覆盖它。

除非你需要进一步与承诺链互动,否则不需要this.allUsers = this.userService.getUsers()所以我在上面的代码中省略了这一点