Javascript 当承诺';s的分辨率取决于设置超时?
此代码段输出Javascript 当承诺';s的分辨率取决于设置超时?,javascript,node.js,multithreading,promise,Javascript,Node.js,Multithreading,Promise,此代码段输出1 4 2 基于我对javascript事件循环和并发模型的理解,这是我所期望的行为。但这给我留下了一些挥之不去的问题 在回答这些问题之前,我将首先详细说明我对这段代码的理解 为什么代码输出1 不需要解释 为什么代码输出4 输出2的回调在0毫秒后加载到事件队列(也称为宏任务队列),但直到主调用堆栈清空后才执行 即使three是立即解决的承诺,其代码也会加载到作业队列(也称为微任务队列)中,并且在主调用堆栈清空之前不会执行(无论事件队列的内容如何) 为什么代码输出2 在console.
1 4 2
基于我对javascript事件循环和并发模型的理解,这是我所期望的行为。但这给我留下了一些挥之不去的问题
在回答这些问题之前,我将首先详细说明我对这段代码的理解
为什么代码输出1
不需要解释
为什么代码输出4
输出2的回调在0毫秒后加载到事件队列(也称为宏任务队列),但直到主调用堆栈清空后才执行
即使three
是立即解决的承诺,其代码也会加载到作业队列(也称为微任务队列)中,并且在主调用堆栈清空之前不会执行(无论事件队列的内容如何)
为什么代码输出2
在console.log(4)
之后,主调用堆栈为空,javascript将查找要加载到主堆栈上的下一个回调。可以非常安全地假设,此时,某个“工作线程”已经将输出2的回调函数放入宏任务队列。这将加载到堆栈中,并输出2
为什么代码不输出3
这对我来说有点模糊。函数three
返回一个承诺,该承诺是然后在主线程中执行的。然后通过传递的回调函数被加载到微任务队列中,并在宏任务队列中的下一个任务之前执行。因此,虽然您可能认为它将在日志为2的回调之前运行,但从理论上讲,它根本不可能运行。这是因为承诺只能通过其setTimeout的回调函数来解析,而回调函数(因为setTimeout)只有在主执行线程(等待承诺解析的同一线程)为空时才会运行
为什么这会困扰我
我试图建立一个完整的javascript如何处理并发性的理论模型。该模型中缺少的一部分是网络请求、承诺和事件循环之间的关系。以上面的代码片段为例,假设我用某种网络请求(异步web开发中非常常见的事情)替换three
的setTimeout。假设网络请求的行为类似于setTimeout,即当“工作线程”完成时,回调被推送到宏任务队列,我很难理解回调是如何执行的。但事实上,这种情况一直都在发生
有人能帮我理解吗?在我目前对js并发性的理解中,我是否有任何遗漏?我是否做出了错误的假设?这有什么意义吗?哈哈
为什么代码不输出3
在此代码中:
console.log('1')
setTimeout(() => {
console.log('2')
}, 0)
function three() {
return new Promise(resolve => {
setTimeout(() => {
return new Promise(resolve => resolve('3'))
},0)
})
}
three().then(result => console.log(result))
console.log('4')
你永远无法解决three()
所创造的第一个承诺。因为这是从three()
返回的处理程序,所以three()中的.then()
处理程序永远不会调用
您确实解析了在计时器内创建的承诺,但是您只将该承诺返回给计时器回调,而计时器回调不做任何操作
如果将代码更改为:
function three() {
return new Promise(resolve => {
setTimeout(() => {
return new Promise(resolve => resolve('3'))
},0)
})
}
three().then(result => console.log(result))
然后,您将看到3
get输出
因此,这与事件循环或其工作方式无关。这与不解析three()
返回的承诺有关,因此该承诺上的.then()
处理程序永远不会被调用
我试图建立一个完整的javascript如何处理并发性的理论模型。该模型中缺少的一部分是网络请求、承诺和事件循环之间的关系。以上面的代码片段为例,假设我将three的setTimeout替换为某种网络请求(这在异步web开发中非常常见)。假设网络请求的行为类似于setTimeout,即当“工作线程”完成时,回调被推送到宏任务队列,我很难理解回调是如何执行的。但事实上,这种情况一直都在发生
网络请求、承诺和计时器都通过事件循环。关于队列中的多个事件在同一时间如何相对于彼此进行优先级排序,有非常复杂的规则.then()
处理程序通常优先排序
可以将Javascript解释器看作是这样一个简单的序列
function three() {
return new Promise(resolve => {
setTimeout(() => {
resolve('3');
},0)
})
}
three().then(result => console.log(result))
请记住,node.js中的网络请求、承诺、计时器和所有异步操作都以这种方式通过事件队列
为什么代码不输出3
在此代码中:
console.log('1')
setTimeout(() => {
console.log('2')
}, 0)
function three() {
return new Promise(resolve => {
setTimeout(() => {
return new Promise(resolve => resolve('3'))
},0)
})
}
three().then(result => console.log(result))
console.log('4')
你永远无法解决three()
所创造的第一个承诺。因为这是从three()
返回的处理程序,所以three()中的.then()
处理程序永远不会调用
您确实解析了在计时器内创建的承诺,但是您只将该承诺返回给计时器回调,而计时器回调不做任何操作
如果将代码更改为:
function three() {
return new Promise(resolve => {
setTimeout(() => {
return new Promise(resolve => resolve('3'))
},0)
})
}
three().then(result => console.log(result))
然后,您将看到3
get输出
因此,这与事件循环或其工作方式无关。这与不解析three()
返回的承诺有关,因此该承诺上的.then()
处理程序永远不会被调用
我试图建立一个完整的javascript如何处理并发性的理论模型。该模型中缺少的一部分是网络请求、承诺和事件循环之间的关系。以上面的代码片段为例,假设我将three的setTimeout替换为某种网络请求(这在异步web开发中非常常见)