Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/411.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 当承诺';s的分辨率取决于设置超时?_Javascript_Node.js_Multithreading_Promise - Fatal编程技术网

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开发中非常常见)