繁体   English   中英

JavaScript许诺.then和setTimeout排序

[英]JavaScript promises .then and setTimeout ordering

 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运行restOfInit ,将字符串记录到控制台,然后将所有用户记录到控制台。 为什么会这样呢?

两件事情:

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

就像@fvgs正确指出的那样,您看到的触发顺序的问题在于this.restOfInit的立即调用-其返回值传递给setTimeout而不是函数本身。

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

    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 ,从外观this.allUsers = res ,它将是一个数组。 我怀疑这可能是您使用setTimeout的原因,因为当您不期望它时,它可能会覆盖它。

除非您需要与this.allUsers = this.userService.getUsers()链进一步交互,否则不需要this.allUsers = this.userService.getUsers()因此我在上面的代码中省略了此方法

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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