Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/429.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
这个具有异步操作的Javascript程序的输出应该是什么?_Javascript_Asynchronous_Ecmascript 6_Es6 Promise_Asynccallback - Fatal编程技术网

这个具有异步操作的Javascript程序的输出应该是什么?

这个具有异步操作的Javascript程序的输出应该是什么?,javascript,asynchronous,ecmascript-6,es6-promise,asynccallback,Javascript,Asynchronous,Ecmascript 6,Es6 Promise,Asynccallback,我希望这段代码运行,然后在2秒钟后,执行堆栈将变为空,并且有一个回调setTimeout。我希望消息队列和作业队列为空(因为承诺尚未解决) 因此,首先打印回调,然后在3秒钟后,解析承诺并将其回调放在作业队列中,并且应打印消息承诺已解析。但事实并非如此。那么我在这里错过了什么 代码是: setTimeout(函数(){ console.log(“Callbcack”); }, 0); 新承诺((解决、拒绝)=>{ 控制台日志(“内部承诺”); 让ms=5000+新日期().getTime(); 而

我希望这段代码运行,然后在2秒钟后,执行堆栈将变为空,并且有一个回调
setTimeout
。我希望消息队列和作业队列为空(因为承诺尚未解决)

因此,首先打印
回调
,然后在3秒钟后,解析承诺并将其回调放在作业队列中,并且应打印消息
承诺已解析
。但事实并非如此。那么我在这里错过了什么

代码是:

setTimeout(函数(){
console.log(“Callbcack”);
}, 0);
新承诺((解决、拒绝)=>{
控制台日志(“内部承诺”);
让ms=5000+新日期().getTime();
而(新日期(){console.log(数据)})
.catch((错误)=>{
控制台日志(err);
})
var ms=2000+新日期().getTime();
而(新日期()
您刚刚发现了JavaScript的。简而言之,实际上有两个不同的回调队列。一个用于微任务,一个用于宏任务。在您的例子中,
Promise
的回调是一个微任务,而
setTimeout
回调是一个宏任务。微任务队列总是在宏任务队列之前处理


因此,即使您在
(数据)=>{console.log(数据)}
之前排队
function(){console.log(“Callbcack”);}
,第二个函数始终会首先执行,无论您在解析
承诺之前阻塞线程多长时间,因为两个队列都将在顶级代码完成执行时处理。

Promise executor函数是同步运行的(正好在您调用新Promise(executor)
时),所以Promise在5000毫秒后运行顶级代码(在初始堆栈)时解析

然后,微任务队列被执行,所以您可以看到
console.log(data)
的结果


然后,js(事件循环)可以自由运行下一个异步块,它恰好是计时器处理程序。

在承诺的回调中有一个阻塞循环,在外部范围中有另一个阻塞循环。这些操作会阻止消息队列被处理。虽然循环不是异步的,即使您将它们放入承诺中。是否有一些异步操作(如从DB获取数据)代替承诺中的for循环,这需要一些时间来处理(比方说10秒)。如果在Time<代码>中间,而<代码>循环……,这两者都不会被处理吗?是的,这正好解释了为什么<代码> SETTIMEOUT> <代码>回调被保证在<代码>承诺> /代码>回调之后执行,这与OP预期的异步操作相反。(setTimeout和promise执行)由Web API或C/C++API(如果环境是Nodejs)处理。那么,我说的2秒钟后,全局执行上下文(顶级)是否正确是否已从调用堆栈中弹出?如果是这种情况,则2秒后全局上下文已从调用堆栈中弹出,现在事件循环在消息队列和微任务队列中查找,此时微任务队列为空,但有一个回调(setTimeout)因此,事件循环将把它放在调用堆栈上并执行它。不完全是这样,因为您还有一个顶级的
Promise
。在
Promise
构造函数中传递的
(resolve,reject)=>{
函数正在同步执行(仅
。然后((数据)=>{console.log(数据)})
是异步的)因此,在您的示例中,执行堆栈在7秒后为空。此时,一个微任务和一个宏任务已排队,因此如果有一些异步操作(如从DB获取数据)代替for循环,它们将以正确的优先级顺序执行,而for循环需要一些时间来处理(比方说10秒)。这会对输出产生任何影响吗?@sv2311如果在初始堆栈上没有调用
resolve
,而是在10秒后异步调用,
console.log(data)
将最后触发。您可以通过使用
setTimeout
假装db调用来检查这一点。