Nodejs承诺解决意外行为
我有以下代码,该代码无法正常工作。
const bar = () => console.log('bar')
const baz = () => console.log('baz')
const myPromise = new Promise((resolve, reject) =>
resolve('should be right after baz, before bar')
);
const foo = () => {
console.log('foo')
setTimeout(bar, 0)
myPromise.then(resolve => console.log(resolve))
baz()
}
foo()
console.log('before bar')
结果:
foo
baz
before bar
should be right after baz, before bar
bar
根据
承诺在当前函数之后立即执行当前函数结束之前解决。
因此,我希望在 foo()
结束后,在bar baz之后,在baz之后,在 console.log('ther bar'之前)
。
有人可以解释为什么不这样做吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在任务队列中添加了传递给
settimeout
的回调,而与承诺履行或拒绝相关的回调是在微任务队列中添加的。这些队列仅在您撰写的JavaScript代码的同步执行后才处理。
结果,在调用任何异步回调之前,请在bar'之前记录。
您的代码如何执行?
脚本执行开始。
函数
bar
,baz
和foo
已定义。也称为Promise构造函数,它导致Resolve
函数的调用,同步解决承诺foo
function解决promise 函数称为'foo'
已在控制台上记录settimeout
被调用,调度<代码> bar 要异步调用。bar
将在任务队列中添加
然后,
方法在myPromise
上调用,安排履行处理程序以异步调用。此履行处理程序是在微型任务队列中添加的baz
函数被调用,记录'baz'
在控制台上foo
函数函数结束。控件返回到下一行foo
被调用last
console.log
语句,记录'bar bar'
控制台脚本执行结束
上登录
'bar'
此时结束,控制台输出如下所示:
任务队列包含执行
bar
函数的任务mypromise
。脚本执行结束后,可以处理任务和微任务队列。
处理微任务队列:
脚本执行是一个任务,并且执行后,MicroTask队列将是第一个要处理的'在控制台上。
最后,处理任务队列,
baz
函数被调用,在控制台上记录'baz'
。以下可能是一本有用的阅读,以了解微任务和任务队列:
Callbacks passed to
setTimeout
are added in the task queue whereas the callbacks related to promise fulfilment or rejection are added in the micro-task queue.These queues are only processed after the synchronous execution of your script, i.e. the javascript code you wrote.
As a result,
'before bar'
is logged before any asynchronous callbacks are invoked.How your code executes?
Script execution starts.
Function
bar
,baz
, andfoo
are defined. Promise constructor is also called which leads to the invocation ofresolve
function, resolving the promise synchronouslyfoo
function is called'foo'
is logged on the consolesetTimeout
is called, schedulingbar
to be called asynchronously.bar
will be added in the task queuethen
method is called onmyPromise
, scheduling the fulfilment handler to be invoked asynchronously. This fulfilment handler is added in the micro-task queuebaz
function is called, logging'baz'
on the consolefoo
function ends. Control return to the next line from wherefoo
was calledLast
console.log
statement is executed, logging'before bar'
on the consoleScript execution ends
At this point, console output is as shown below:
and the task queue contains a task to execute the
bar
function whereas the micro-task queue contans a micro-task to execute the fulfilment handler of themyPromise
.After the script execution ends, task and micro-task queues can be processed.
The micro-task queue is processed:
Script execution is a task and after its execution, micro-task queue will be the first one to be processed, logging
'should be right after baz, before bar'
on the console.At last, the task queue is processed,
baz
function is called, logging'baz'
on the console.Following might be a helpful read to understand the micro-task and the task queue: JavaScript async callbacks - Promise and setTimeout
您可能会在下面找到摘要的片段:
The MDN documentation for
Promise.prototype.then
states (emphasis is mine):You might find the snippet below enlightening:
如果想了解异步概念,则应查看此很棒的。
在此处运行的顺序
我将尝试向您解释代码如何首先 ,我们正在用功能初始化所有变量。
然后,我们正在调用
foo()
,然后 console.log('baz')。调用
foo
是foo
将输入 stack 。和foo
已登录到控制台。然后
settimeout(bar,0)
被调用。settimeout(bar,0)
为异步,将在稍后调用,并将其推入回调队列(当堆栈为空时,稍后将调用)。这就是为什么我们没有看到bar
的控制台。在此
mypromise.then(resolve =&gt; console.log(resolve))
被调用之后。这也是异步调用。因此,这也将被推到回调队列。然后将执行
baz()
。这就是为什么我们在foo
之后看到baz
的日志的原因。现在记住,我们在堆栈中
console.log('ther bar')
,因此将首先记录下来。之后,将调用所有回调队列中的所有项目。到目前为止已记录三件事: -
foo
BAZ
现在在bar
现在,关于承诺的好处是,他们在回调队列中被优先考虑。因此,即使
settimeout
在我们的承诺之前被调用,如果承诺是执行,它将是优先级。这就是为什么
'应该在BAZ之后立即进行的原因,然后在BAR'
之前调用bar
。If want to understand the asynchronous concept, you should check out this awesome video.
I'll try to explain to you the sequence of how the code is running here
First of all, we are Initializing all the variables with functions.
Then we're calling
foo()
, and laterconsole.log('before baz')
.What will happen on calling
foo
isfoo
will enter the stack. Andfoo
is logged into the console.Then
setTimeout(bar, 0)
is being called.setTimeout(bar, 0)
being asynchronous, will be called later and pushed in the callback queue(this will be called later when the stack is empty). That's why we didn't see the console ofbar
.After this
myPromise.then(resolve => console.log(resolve))
is called. And this is also an asynchronous call. So this will also be pushed to the callback queue.Then
baz()
will be executed. And that's why we're seeing a log ofbaz
after thefoo
.Now remember, we've
console.log('before bar')
in the stack, so this will be logged first. And after this all the items in the callback queue will be called.Three things are logged up to now:-
foo
baz
before bar
Now, the good thing about promises is they are being prioritized in the callback queue, over anything. So even
setTimeout
is being called before the our promise, if promise is executed, it will be prioritized.That's the reason why
'should be right after baz, before bar'
is called beforebar
.