Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/google-chrome/4.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_Google Chrome_Promise_Settimeout_Es6 Promise - Fatal编程技术网

Javascript、承诺和设置超时

Javascript、承诺和设置超时,javascript,google-chrome,promise,settimeout,es6-promise,Javascript,Google Chrome,Promise,Settimeout,Es6 Promise,我一直在玩弄承诺,但我很难理解以下代码发生了什么: const promise = new Promise((resolve, reject) => { console.log('Promise started - Async code started') setTimeout(() => { resolve('Success') }, 10) }) setTimeout(() => { console.log('Promise log inside

我一直在玩弄承诺,但我很难理解以下代码发生了什么:

const promise = new Promise((resolve, reject) => {
  console.log('Promise started - Async code started')
  setTimeout(() => {
    resolve('Success')
  }, 10)
})

setTimeout(() => {
  console.log('Promise log inside first setTimeout')
}, 0)

promise.then(res => {
  console.log('Promise log after fulfilled')
})

console.log('Promise made - Sync code terminated')

setTimeout(() => {
  console.log('Promise log inside second setTimeout')
}, 0)
输出为:


Promise started - Async code started 
Promise made - Sync code terminated 
Promise log inside first setTimeout 
Promise log inside second setTimeout 
Promise log after fulfilled

Promise started - Async code started 
Promise made - Sync code terminated 
Promise log after fulfilled 
Promise log inside first setTimeout 
Promise log inside second setTimeout 
正如所料

但让我们检查以下代码的输出:

const promise = new Promise((resolve, reject) => {
  console.log('Promise started - Async code started')
  setTimeout(() => {
    resolve('Success')
  }, 1)
})

setTimeout(() => {
  console.log('Promise log inside first setTimeout')
}, 0)

promise.then(res => {
  console.log('Promise log after fulfilled')
})

console.log('Promise made - Sync code terminated')
setTimeout(() => {
  console.log('Promise log inside second setTimeout')
}, 0)
将要解析的承诺设置超时计时器值从10ms更改为1ms

输出为:


Promise started - Async code started 
Promise made - Sync code terminated 
Promise log inside first setTimeout 
Promise log inside second setTimeout 
Promise log after fulfilled

Promise started - Async code started 
Promise made - Sync code terminated 
Promise log after fulfilled 
Promise log inside first setTimeout 
Promise log inside second setTimeout 
对此有何解释?

来自

  • setTimeout
    在计时器过期后不会立即运行
  • 零延迟并不意味着回拨将在零毫秒后触发。以0(零)的延迟调用
    setTimeout
    毫秒不会在给定时间后执行回调函数 间隔 基本上,
    setTimeout
    需要等待队列消息的所有代码完成,即使您指定了特定的时间限制 为您的设置超时
如果设置2毫秒和1毫秒,会发生什么情况:

const promise = new Promise((resolve, reject) => {
  console.log('Promise started - Async code started')
  setTimeout(() => {
    resolve('Success')
  }, 2)
})

console.log('Promise log inside first setTimeout 1')
setTimeout(() => {
  console.log('Promise log inside first setTimeout 2')
}, 1)

promise.then(res => {
  console.log('Promise log after fulfilled ❌')

})

console.log('Promise log inside second setTimeout 1')
setTimeout(() => {
  console.log('Promise log inside second setTimeout 2')
}, 1)
});
输出始终为:

Promise started - Async code started
Promise log inside first setTimeout 1
Promise log inside second setTimeout 1
Promise log inside first setTimeout 2
Promise log inside second setTimeout 2
Promise log after fulfilled ❌
结论
如果你想要一个正确的行为,就应该消除零延迟。

我将使用以下示例来解释:

setTimeout(() => {
  console.log('1 ms timeout');
}, 1);                            // Moved to async queue at time = T0
setTimeout(() => {
  console.log('0 ms timeout')
}, 0);                            // Moved to async queue after 1 ms that synchronous call to setTimeout takes i.e. at T1
                                  // So at T1, queue will be [("1ms timeout", 0), ("0ms timeout", 0)]
因此,这将打印

1 ms timeout
0 ms timeout
对上述内容的理解: 调用setTimeout是同步的(即使它的回调被放在异步队列中),也就是说,我们调用setTimeout()并转到下一个语句-此同步操作本身可能需要1ms

换句话说,1ms的时间太低,所以当JS引擎看到第二条异步语句时,第一条语句已经在队列中花费了1ms

我还建议您尝试以下方法

setTimeout(() => {
  console.log("First");
}, 2);                      // queue at T0 = [("First", 2)]

const forLoopLimit = 100;
for (var i = 0; i < forLoopLimit; i++){
    console.log(i * 10000);
}                           // Assume that it takes about 3 milliseconds
                            // queue at T3 = [("First", 0)]
setTimeout(() => {
  console.log("Second");
}, 0);                      // Assume it takes 0 milliseconds.
                            // queue at T4 = [("First", 0), ("Second", 0)]
多次尝试上面的内容,您会发现有时候控制台日志会有不同的时间戳。大致上,您可以说
console.log()
Date.now()
需要0.5ms。现在是调用/执行同步的时候了

因此,对于Chrome,所有
setTimeout(fn,0)
都会转换为
setTimeout(fn,1)
,并计划在您计划的第一个之后触发(请记住,承诺构造函数是同步调用的)

所以我们可以用

setTimeout(()=>console.log('1ms delay'),1);

setTimeout(()=>console.log('0ms delay'),0)。在这种情况下,不同的浏览器(JavaScript引擎)表现不同。看起来Chrome无法区分非常小的延迟和
0
。可能的重复。
1
被视为是
0
,在这种情况下,日志又开始有意义了。@Bergi它实际上是
0
,在Chrome中被视为
1
。但这仍然不能解释为什么1ms超时被安排在0ms之前触发,即使执行回调之前发生的事情需要很长时间,它们应该先安排0毫秒,然后安排1毫秒,就像你的1和2示例一样,这很可能不会在计划完成后1和2毫秒触发。1ms调用setTimeout?认真地Nhaa,你可能在一个非常幸运的日子,你在T00:00:00.00999给第一个打电话。。。第二个是T:00:00:00.0100,但仅此而已,不是确定性行为,而是随机行为。