【问题标题】:Node.js: Asynchronous Callback Execution. Is this Zalgo?Node.js:异步回调执行。这是扎尔戈吗?
【发布时间】:2017-03-15 11:02:49
【问题描述】:

使用 node - 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 吗?谁能给我一个实时的例子,这会导致严重的故障吗?

【问题讨论】:

  • 你能解释一下为什么你期望A,B,C吗?
  • 我以为 A(B) 的回调会被延迟,同时 B() 会被执行
  • 通过什么机制延期? callback 很容易被命名为 andNowCallThisFunctionImmediately - 它只是一个变量名
  • @Sathish In A(C), C 是可能被延迟的回调
  • 回调没有执行任何输入/输出。为什么会延期?

标签: javascript node.js asynchronous


【解决方案1】:

不,这些都不是 zalgo。你的第一个A 函数总是同步调用它的回调,并且应该这样记录。你的第二个A 函数总是异步调用它的回调,并且应该这样记录。这没有什么问题,我们每天使用数千个。 A C BA B C 的输出是确定性的

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

function A(callback) {
  console.log('A');
  if (Math.random() < 0.5) {
    callback();
  } else {
    process.nextTick(callback);
  }
}

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

【讨论】:

  • 感谢您解释 Zalgo 是什么(我之前没见过这个词),所以我可以更新我的答案,希望能提供比我之前发布的更好的解释。
【解决方案2】:

首先让我解释一下代码是如何工作的——看看我添加的代码中的 cmets:

// 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});
    });
}

现在,如果有错误参数,回调可以在 x() 返回之前立即运行,否则在 x() 返回之后运行。这段代码很常见。为了测试参数,人们可能会争辩说它应该抛出一个异常,但让我们暂时忽略这一点,可能有一些更好的立即知道的操作错误示例 - 这只是一个简单的示例。

现在,如果它是这样写的:

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});
    });
}

将保证在x() 返回之前永远不会调用回调。

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

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};

那么它有时会在不带process.nextTickx() 版本中崩溃,而在带有process.nextTick()x() 版本中永远不会崩溃。

【讨论】:

    猜你喜欢
    • 2023-03-04
    • 2013-02-02
    • 2015-07-09
    • 2017-03-20
    • 2014-03-20
    • 1970-01-01
    • 2014-11-21
    • 2016-05-01
    相关资源
    最近更新 更多