简体   繁体   English

Javascript承诺像我期望的那样工作

[英]Javascript Promises dosent work like I expect

I am trying to understand promises and getting a bit confused here. 我试图理解承诺,在这里有些困惑。 I am playing with different scenarios and I stack on one of them. 我在玩不同的场景,我在其中之一上叠加。 Why doesn't let third = function() wait for let second = function() to stop counting? 为什么let third = function()等待let second = function()停止计数?

 let first = function () { return new Promise(function (resolve, reject) { setTimeout(function () { console.log('first'); resolve() }, 3000) }) } let second = function () { return new Promise(function (resolve, reject) { let iter = 7 console.log(iter); for (let i = 0; i <= iter; i++) { (function(n) { setTimeout(function(){ console.log('hi'); console.log(n); }, 400 * i); }(i)*i); } console.log('seco'); resolve(); }) } let third = function() { return new Promise(function (resolve, reject) { console.log('thir'); resolve() }) }; let scenario = function() { first() .then(() => second()) .then(() => third()) } scenario() 

setTimeout doesn't wait for the function to return - it just schedules it to be executed later. setTimeout不等待函数返回-只是安排它稍后执行。 The call to setTimeout returns immediately and your task finishes after that. setTimeout的调用将立即返回,并且您的任务将在此之后完成。

To wait for the scheduled function to execute after a certain period of time, call resolve() at the end of the delayed function. 要在一段时间后等待调度的函数执行,请在延迟函数的末尾调用resolve() That way the promise will only be completed once the scheduled function executes. 这样,仅当计划功能执行后,诺言才会完成。

It is because for loop won't wait for your setTimeout method to execute. 这是因为for循环不会等待您的setTimeout方法执行。 Every time the for loop encounters the setTimeout method, JS will call the event loop and place it there (to be executed once it times out) and move forward. 每当for循环遇到setTimeout方法时,JS都会调用事件循环并将其放置在该循环中(一旦超时将执行)并向前移动。 That's why it calls your resolve before printing the console.log statements from the setTimeout method. 这就是为什么它在从setTimeout方法打印console.log语句之前调用您的resolve的原因。 For an analogy, check this 打个比方,检查一下

for (let i= 0; i< 5; i++) {
  setTimeout(() => {
    console.log('I am inside');
  }, 1000);

  console.log('I am outside')
}

It will print I am outside first (5 times) and then I am inside . 它会先打印“ I am outside (5次),然后再打印“ I am inside

It is possible to create this effect, but you need to put your resolve() in its own setTimeout() , adjusting the second parameter such that there is sufficient time for the other timeouts to complete. 可以创建此效果,但是您需要将resolve()放在其自己的setTimeout() ,调整第二个参数,以便有足够的时间来完成其他超时。

 const first = new Promise((resolve, reject) => { setTimeout(() => { resolve('First promise resolved!') }, 400) }) const second = new Promise((resolve, reject) => { let iter = 7 for (let i = 1; i < iter; i++) { setTimeout(() => { console.log("Iteration: ", i) }, i * 500) } setTimeout(() => { resolve('Second promise resolved!') }, iter * 500) }) first .then(res => console.log(res)) .then(() => second .then(res => console.log(res))) 

EDIT: Just to note, the for loop will start printing as soon as second is defined. 编辑:只是要注意, for循环将在second定义后立即开始打印。 If you want to wait for this loop to start, you should add it inside .then() so that it triggers after the first promise has been resolved. 如果要等待此循环开始,则应将其添加到.then().then()以便在解决第一个承诺后触发。

@johnnybigH, The second function resolve's outside of timeout so technically it will not wait for timeout function to complete as you are resolving it out of setTimeout. @johnnybigH,第二个函数解决超时问题,因此从技术上讲,它不会等待超时函数完成,因为您正在从setTimeout中解决超时问题。 Now 2nd one is resolved so it is going for the execution of the third function. 现在解决第二个问题,以便执行第三个功能。 What you can do is inside of 2nd function for the loop. 您可以在循环的2nd函数内部进行操作。 look for the last iteration and resolve the end function. 寻找最后的迭代并解析结束函数。

for (let i = 0; i <= iter; i++) {
        (function(n) {
            setTimeout(function(){
                console.log('hi');
                console.log(n);
            if(i == iter) resolve();
            }, 400 * i);
        }(i)*i);
    }

This is the expected behavior. 这是预期的行为。

The setTimeouts will not demonstrate expected order since the functions themselves resolved in the order as defined in the promise. setTimeouts不会显示预期的顺序,因为函数本身按承诺中定义的顺序解析。 Just replace the setTimeouts with console.log()'s and you will see the order executed as defined. 只需将setTimeouts替换为console.log(),您将看到按定义执行的顺序。

Well, you call resolve() inside of your for loop. 好吧,您可以 for循环中调用resolve() You should place it outside of the for loop so that it waits for the loop to finish. 您应该将其放置在for循环之外,以便它等待循环结束。

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

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