Javascript Node.js:异步回调执行。这是Zalgo吗?

Javascript Node.js:异步回调执行。这是Zalgo吗?,javascript,node.js,asynchronous,Javascript,Node.js,Asynchronous,使用节点-6.0执行以下操作。 function A(callback) { console.log('A'); callback(); } function B() { console.log('B') } function C() { console.log('C'); } A(C); B(); // Result is A,C,B i expected that A, B, C 但将上述示例更改为使用process.nextTick()打印A、B、C funct

使用节点-6.0执行以下操作。

function A(callback) {
  console.log('A');
  callback();
}

function B() {
  console.log('B')
}

function C() {
  console.log('C');
}

A(C);
B();


// Result is A,C,B i expected that A, B, C
但将上述示例更改为使用process.nextTick()打印A、B、C

function A(callback) {
  console.log('A');
  process.nextTick(() => {
    callback();
  });
}

function B() {
  console.log('B')
}

function C() {
  console.log('C');
}

A(C);
B();

这就是我们所说的zalgo吗?有谁能给我一个实时的例子,这将导致严重的故障吗?

首先让我解释一下代码是如何工作的-请参阅我添加的代码中的注释:

// first you define function A and nothing happens:
function A(callback) {
  console.log('A');
  callback();
}

// then you define function B and nothing happens:    
function B() {
  console.log('B')
}

// then you define function C and nothing happens:
function C() {
  console.log('C');
}

// now you call function A with argument C:
A(C);
// when A runs it prints 'A' and calls C before it returns
// now the C runs, prints C and returns - back to A
// A now has nothing more to do and returns

// Now the execution continues and B can be run:
B();
// B runs and prints 'B'
这与Java、C等任何语言中的情况完全相同

现在,第二个例子:

// first you define function A and nothing happens:
function A(callback) {
  console.log('A');
  process.nextTick(() => {
    callback();
  });
}

// then you define function B and nothing happens:
function B() {
  console.log('B')
}

// then you define function C and nothing happens:
function C() {
  console.log('C');
}

// Then you run A with C passed as an argument:
A(C);
// A prints 'A' and schedules running an anonymous function:
// () => { callback(); }
// on the next tick of the event loop, before I/O events are handled
// but after the current code stack is unrolled
// then it returns
// And then B is run:
B();
// B prints 'B' and returns
// Now nothing else is left to do so the next tick of the event loop starts
// There's one function to run, scheduled earlier so it runs.
// This function runs the `callback()` which was `C`
// so C starts, prints 'C' and returns
// The anonymous function has nothing else to do and returns
// There is no more things on the event loop so the program exits
更新 感谢Bergi在他的回答中解释了Zalgo是什么。现在我更好地理解你的担忧

这就是我们所说的zalgo吗?谁能给我一个实时的例子,这将导致重大故障

我见过很多这样的代码:

function x(argument, callback) {
    if (!argument) {
        return callback(new Error('Bad argument'));
    }
    runSomeAsyncFunction(argument, (error, result) => {
        if (error) {
            return callback(new Error('Error in async function'));
        }
        callback({data: result});
    });
}
function x(argument, callback) {
    if (!argument) {
        return process.nextTick(callback, new Error('Bad argument'));
    }
    runSomeAsyncFunction(argument, (error, result) => {
        if (error) {
            return callback(new Error('Error in async function'));
        }
        callback({data: result});
    });
}
let a;
x('arg', (err, result) => {
    // assume that 'a' has a value
    console.log(a.value);
});
// assign a value to 'a' here:
a = {value: 10};
现在,如果有错误的参数,回调可以在
x()
返回之前立即运行,否则在
x()
返回之后运行。这段代码非常常见。为了测试参数,我们可以说它应该抛出一个异常,但让我们暂时忽略这一点,可能有一些更好的操作错误示例可以立即知道-这只是一个简单的示例

如果是这样写的:

function x(argument, callback) {
    if (!argument) {
        return callback(new Error('Bad argument'));
    }
    runSomeAsyncFunction(argument, (error, result) => {
        if (error) {
            return callback(new Error('Error in async function'));
        }
        callback({data: result});
    });
}
function x(argument, callback) {
    if (!argument) {
        return process.nextTick(callback, new Error('Bad argument'));
    }
    runSomeAsyncFunction(argument, (error, result) => {
        if (error) {
            return callback(new Error('Error in async function'));
        }
        callback({data: result});
    });
}
let a;
x('arg', (err, result) => {
    // assume that 'a' has a value
    console.log(a.value);
});
// assign a value to 'a' here:
a = {value: 10};
可以保证在
x()
返回之前不会调用回调

现在,这是否会导致“重大故障”完全取决于它的使用方式。如果您运行类似这样的操作:

function x(argument, callback) {
    if (!argument) {
        return callback(new Error('Bad argument'));
    }
    runSomeAsyncFunction(argument, (error, result) => {
        if (error) {
            return callback(new Error('Error in async function'));
        }
        callback({data: result});
    });
}
function x(argument, callback) {
    if (!argument) {
        return process.nextTick(callback, new Error('Bad argument'));
    }
    runSomeAsyncFunction(argument, (error, result) => {
        if (error) {
            return callback(new Error('Error in async function'));
        }
        callback({data: result});
    });
}
let a;
x('arg', (err, result) => {
    // assume that 'a' has a value
    console.log(a.value);
});
// assign a value to 'a' here:
a = {value: 10};

然后它有时会在没有进程的
x()
版本中崩溃。nextTick也不会在有进程的
x()
版本中崩溃。nextTick()不,这两个版本都不是zalgo。您的第一个
函数总是同步调用其回调函数,并且应该这样记录。您的第二个
函数始终异步调用其回调函数,并且应该这样记录。这没什么错,我们每天都要用上千个。输出
A C B
A B C
是确定性的

指回调是否异步的不确定性

function A(callback) {
  console.log('A');
  if (Math.random() < 0.5) {
    callback();
  } else {
    process.nextTick(callback);
  }
}
函数A(回调){
console.log('A');
if(Math.random()<0.5){
回调();
}否则{
process.nextTick(回调);
}
}

调用
A(C)的输出;B()
将是完全不可预测的。

你能解释一下为什么你期望
A,B,C
?我认为A(B)的回调将被取消,而B()将通过什么机制被推迟执行<代码>回调
可以很容易地命名为
,现在立即调用此函数
——它只是一个变量name@Sathish在
A(C)
中,
C
是可能延迟的回调。回调不执行任何输入/输出。为什么要推迟呢?谢谢你解释什么是Zalgo(我以前没见过这个词),所以我可以更新我的答案,希望比我之前发布的更好。