我一直试图解决我遇到的问题,但没有成功,因此我请求你的帮助。
让我们考虑以下示例:
const async = require('async')
var counter = 0
var test = cb => {
if (++counter < 3) {
setTimeout( () => {
async.each([0,1,2], (item, callback) => {
console.log(item)
console.log('counter inner ' + counter)
test(cb)
callback()
}, () => {
cb()
})
})
} else {
console.log('counter ' + counter)
}
}
var prom = new Promise( (res, rej) => test( () => res('done') ) )
prom.then(res => console.log(res))
输出结果为:
0
counter inner 1
1
counter inner 2
counter 3
2
counter inner 3
counter 4
done
0
counter inner 4
counter 5
1
counter inner 5
counter 6
2
counter inner 6
counter 7
我不明白的是在第二个counter inner 4
之后它是如何打印0
的。不应该打印counter inner 1
?一个承诺只被解决一次?第二次解决呼叫会发生什么?谢谢。
答案 0 :(得分:0)
有点难以一步一步地解释它,但我会向后试试 - 意思是从你的输出中我会试着提到代码中的哪一行输出它以及何时。
// obviously starting inside the callback async runs for each of your 3 items
0 // console.log(item);
counter inner 1 // console.log('counter inner ' + counter);
1 // console.log(item);
counter inner 2 // console.log('counter inner ' + counter);
counter 3 // let's not forget you also call callback() for each item
// which evaluates this condition if (++counter < 3) and starting from here,
// it will be true and will run your else statement
// console.log('counter ' + counter);
2 // console.log(item);
counter inner 3 // console.log('counter inner ' + counter);
counter 4 // console.log('counter ' + counter);
// at this point your promise is already resolved (and yes, only once)
done // prom.then(res => console.log(res))
// Now you are probably questioning where the following output comes from
// remember this condition? if (++counter < 3)
// before starting to evaluate to false and printing to console, once it
// evaluated to true so setTimeout was called with your async callback
// which scheduled it to run on the next "tick"*, which is right after the
// promised was resolved
0
counter inner 4
counter 5
1
counter inner 5
counter 6
2
counter inner 6
counter 7
这是setTimeout()
超时为0的效果。它就像C中的线程/进程产量。虽然它似乎说“立即运行”,但实际上它会在执行队列的末尾重新排队新的javaScript代码。
根据setTimeout
文档,其第二个参数如下:
计时器应该以毫秒(千分之一秒)为单位的时间 在执行指定的函数或代码之前等待。如果这 省略参数,使用值0,表示执行 “立即”,或更准确地说,尽快。请注意 无论哪种情况,实际延迟可能比预期的长;
在这里,您可以阅读有关reasons for delays longer than specified的更多信息。
您可以通过将if
条件更改为if(++counter < 2)
来轻松验证我刚刚解释的内容。由于它永远不会评估为true,因此您将看到控制台输出在"done"
停止。