简体   繁体   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); } 

In the attached snippet, I would expect the logging of all the users to happen before the restOfInit function, since there's a difference of 2 seconds between the timeouts. 在所附的代码段中,我希望所有用户的日志记录都在restOfInit函数之前进行,因为超时之间相差2秒。 However, what actually happens is that restOfInit is run first, logging a string to console, and all the users are logged to console after that. 但是,实际上发生的是, restOfInit运行restOfInit ,将字符串记录到控制台,然后将所有用户记录到控制台。 Why is this happening? 为什么会这样呢?

Two things: 两件事情:

1) The functions passed to setTimeout() execute asynchronously in approximately the number of milliseconds specified. 1)传递给setTimeout() )的函数大约在指定的毫秒数内异步执行。 You're likely aware of this. 您可能知道这一点。 However, the calls to setTimeout() return (almost immediately) without regard to the time specified. 但是,对setTimeout()的调用将返回(几乎立即),而不考虑指定的时间。

2) You want to pass this.restOfInit instead of this.restOfInit() . 2)您想传递this.restOfInit而不是this.restOfInit() The former passes the function to setTimeout() . 前者将函数传递给setTimeout() The latter invokes the function with no arguments and passes the return value (possibly undefined ) to setTimeout(). 后者不带任何参数调用该函数,并将返回值(可能是undefined )传递给setTimeout()。

tldr; tldr;

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

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

As correctly stated by @fvgs, the problem with the firing order you are seeing lies with the immediate invocation of this.restOfInit - its return value being passed to setTimeout instead of the function itself. 就像@fvgs正确指出的那样,您看到的触发顺序的问题在于this.restOfInit的立即调用-其返回值传递给setTimeout而不是函数本身。

However using timeouts here defeats the point of promises. 但是,在此使用超时将无法兑现承诺。 Promises should allow you to schedule the order precisely, and will execute as quickly as they can, rather than a guaranteed waiting period no matter how fast your request for users takes. 承诺应该允许您精确地安排订单,并且将尽可能快地执行订单,而不是保证的等待期,无论您对用户的请求有多快。 Yours actually does not need to be chained at all as only the first callback needs the resolution values. 实际上,您的链接根本不需要链接,因为只有第一个回调需要分辨率值。 It would be far easier to schedule like this... 这样安排时间会容易得多...

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

Also side note - the assigning of the this.allUsers = this.userService.getUsers() chain will be a promise, but then in the callback you assign this.allUsers = res which by the looks of it will be an array. 另外要注意的是-分配this.allUsers = this.userService.getUsers()链是一个承诺,但随后在回调中分配this.allUsers = res ,从外观this.allUsers = res ,它将是一个数组。 I suspect this may be the reason you have used setTimeout as it could be overwriting it when you don't expect it. 我怀疑这可能是您使用setTimeout的原因,因为当您不期望它时,它可能会覆盖它。

Unless you need to further interact with the promise chain there is no need for this.allUsers = this.userService.getUsers() so i have omitted this in the code above 除非您需要与this.allUsers = this.userService.getUsers()链进一步交互,否则不需要this.allUsers = this.userService.getUsers()因此我在上面的代码中省略了此方法

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

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