Javascript 异步代码执行说明

Javascript 异步代码执行说明,javascript,node.js,asynchronous,es6-promise,Javascript,Node.js,Asynchronous,Es6 Promise,我一直试图把我的头围绕在我的问题上,但没有成功,因此我请求你的帮助 我们考虑下面的例子: const async = require('async') var counter = 0 var test = cb => { if (++counter < 3) { setTimeout( () => { async.each([0,1,2], (item, callback) => { console.log(item)

我一直试图把我的头围绕在我的问题上,但没有成功,因此我请求你的帮助

我们考虑下面的例子:

const async = require('async')
var counter = 0

var test = cb => {
  if (++counter < 3) {
    setTimeout( () => {
      async.each([0,1,2], (item, callback) => {
        console.log(item)
        console.log('counter inner ' + counter)
        test(cb)
        callback()
      }, () => {
          cb()
       })
    })
  } else {
      console.log('counter ' + counter)
  } 
}

var prom = new Promise( (res, rej) => test( () => res('done') ) )
prom.then(res => console.log(res))

我不明白的是,它是如何在第二个
0
之后打印的
计数器内部4
。不应打印
计数器内部1
?承诺只解决一次?第二个解析调用会发生什么?谢谢。

一步一步地解释它有点困难,但我会倒过来试试——这意味着从您的输出中,我会尝试提及代码中的哪一行输出了它,以及何时输出

// obviously starting inside the callback async runs for each of your 3 items

    0 // console.log(item);
    counter inner 1 // console.log('counter inner ' + counter);

    1 // console.log(item);
    counter inner 2 // console.log('counter inner ' + counter);
    counter 3 // let's not forget you also call callback() for each item 
             // which evaluates this condition if (++counter < 3) and starting from here,
             // it will be true and will run your else statement
             // console.log('counter ' + counter);

    2 // console.log(item);
    counter inner 3 // console.log('counter inner ' + counter);
    counter 4 // console.log('counter ' + counter);

// at this point your promise is already resolved (and yes, only once)
    done // prom.then(res => console.log(res))

// Now you are probably questioning where the following output comes from
// remember this condition? if (++counter < 3)
// before starting to evaluate to false and printing to console, once it
// evaluated to true so setTimeout was called with your async callback
// which scheduled it to run on the next "tick"*, which is right after the
// promised was resolved

    0
    counter inner 4
    counter 5 
    1 
    counter inner 5
    counter 6
    2
    counter inner 6
    counter 7
//显然是从回调异步内部开始为3个项中的每一项运行
0//console.log(项);
计数器内部1//console.log('counter-internal'+计数器);
1//console.log(项);
计数器内部2//console.log('计数器内部'+计数器);
计数器3//不要忘记,您还可以为每个项目调用callback()
//如果(++计数器<3)并从这里开始计算该条件,
//它将是真实的,并将运行您的else语句
//console.log('计数器'+计数器);
2//console.log(项);
计数器内部3//console.log('counter-internal'+计数器);
计数器4//console.log(“计数器”+计数器);
//在这一点上,您的承诺已经解决(是的,只有一次)
完成//prom.then(res=>console.log(res))
//现在,您可能会质疑以下输出来自何处
//还记得这种情况吗?如果(++计数器<3)
//在开始计算为false并打印到控制台之前
//计算结果为true,因此使用异步回调调用了setTimeout
//它计划在下一个“勾选”*,即
//承诺已经解决
0
计数器内部4
柜台5
1.
计数器内部5
柜台6
2.
计数器内部6
柜台7
这就是超时为0的
setTimeout()
所产生的效果。这就像C中的线程/进程产出。虽然它似乎说“立即运行”,但实际上它在执行队列的末尾重新排队新的javaScript代码

根据
setTimeout
文档,其第二个参数如下:

时间,以毫秒(千分之一秒)为单位,计时器应 在执行指定的函数或代码之前等待。如果这 参数,使用值0,表示执行 “立即”,或者更准确地说,尽快。注意,在 无论哪种情况,实际延迟都可能比预期的时间长

在这里,你可以阅读更多关于

通过将
if
条件更改为
if(++计数器<2)
,您可以轻松验证我刚才解释的内容。由于它的计算结果永远不会为true,因此您将看到控制台输出在
“done”处停止
// obviously starting inside the callback async runs for each of your 3 items

    0 // console.log(item);
    counter inner 1 // console.log('counter inner ' + counter);

    1 // console.log(item);
    counter inner 2 // console.log('counter inner ' + counter);
    counter 3 // let's not forget you also call callback() for each item 
             // which evaluates this condition if (++counter < 3) and starting from here,
             // it will be true and will run your else statement
             // console.log('counter ' + counter);

    2 // console.log(item);
    counter inner 3 // console.log('counter inner ' + counter);
    counter 4 // console.log('counter ' + counter);

// at this point your promise is already resolved (and yes, only once)
    done // prom.then(res => console.log(res))

// Now you are probably questioning where the following output comes from
// remember this condition? if (++counter < 3)
// before starting to evaluate to false and printing to console, once it
// evaluated to true so setTimeout was called with your async callback
// which scheduled it to run on the next "tick"*, which is right after the
// promised was resolved

    0
    counter inner 4
    counter 5 
    1 
    counter inner 5
    counter 6
    2
    counter inner 6
    counter 7