如何防止 Node.js 在等待回调时退出?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6442676/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 14:18:47  来源:igfitidea点击:

How to prevent Node.js from exiting while waiting for a callback?

node.js

提问by mikl

I have code like this:

我有这样的代码:

var client = new mysql.Client(options);
console.log('Icanhasclient');

client.connect(function (err) {
  console.log('jannn');
  active_db = client;
  console.log(err);
  console.log('hest');

  if (callback) {
    if (err) {
      callback(err, null);
    }

    callback(null, active_db);
  }
});

My problem is that Node terminates immediately when I run it. It prints 'Icanhasclient', but none of the console.log's inside the callback are called.

我的问题是 Node 在我运行时立即终止。它打印“Icanhasclient”,但没有调用回调中的任何 console.log。

(mysql in this example is node-mysql.

(本例中的 mysqlnode-mysql

Is there something that can be done to make node.js wait for the callback to complete before exiting?

有什么办法可以让 node.js 在退出之前等待回调完成?

采纳答案by george calvert

Callback is Not Queued

回调未排队

Node runs until all event queuesare empty. A callback is added to an event queuewhen a call such as

节点运行直到所有事件队列都为空。当调用时将回调添加到事件队列,例如

  emmiter1.on('this_event',callback).

has executed. This call is part of the code written by the module developer .

已执行。此调用是模块开发人员编写的代码的一部分。

If a module is a quick port from a synchronous/blocking version, this may not happen til some part of the operation has completed and all the queues might empty before that occurs, allowing node to exit silently.

如果模块是来自同步/阻塞版本的快速端口,这可能不会发生,直到操作的某些部分完成并且所有队列可能在此之前清空,从而允许节点静默退出。

This is a sneaky bug, that is one that the module developer might not run into during development, as it will occur less often in busy systems with many queuesas it will be rare for all of them to be empty at the critical time.

这是一个偷偷摸摸的错误,这是模块开发人员在开发过程中可能不会遇到的错误,因为它在具有许多队列的繁忙系统中发生的频率较低,因为在关键时刻所有队列都为空的情况很少见。

A possible fix/bug detector for the user is to insert a special timer event before the suspect function call.

用户可能的修复/错误检测器是在可疑函数调用之前插入一个特殊的计时器事件。

回答by Todd

You can just issue a setTimeout or a recurring timeout with setInterval.

您可以使用 setInterval 发出 setTimeout 或重复超时。

If you want to check for exit conditions, you can also do a conditional timeout:

如果要检查退出条件,还可以执行条件超时:

(function wait () {
   if (!SOME_EXIT_CONDITION) setTimeout(wait, 1000);
})();

Put this at the end of your code and the console will just wait ... and wait ... until you want it to close.

把它放在你的代码的末尾,控制台会一直等……等……直到你想要它关闭。

回答by you786

My solution was to instantiate an EventEmitter, and listen for my custom event.

我的解决方案是实例化一个 EventEmitter,并监听我的自定义事件。

var eventEmitter = new process.EventEmitter();

then I called eventEmitter.emitfrom the async callback:

然后我eventEmitter.emit从异步回调中调用:

client.connect(function (err) {
    eventEmitter.emit('myevent', {something: "Bla"})
});

The last thing in my script was the eventEmitter.on:

我的脚本中的最后一件事是eventEmitter.on

eventEmitter.on('myevent', function(myResult){
  // I needed the result to be written to stdout so that the calling process could get it
  process.stdout.write(JSON.stringify(myResult));
});

Node will then wait until the event handler finishes running.

然后节点将等待事件处理程序完成运行。

回答by Francisco Presencia

Based on @Todd's answer, I created a one-liner. Include it in the beginning of your script, and set done = truewhen you are done:

根据@Todd 的回答,我创建了一个单线。将其包含在脚本的开头,并done = true在完成后设置:

var done = (function wait () { if (!done) setTimeout(wait, 1000) })();

Example:

例子:

var done = (function wait () { if (!done) setTimeout(wait, 1000) })();

someAsyncOperation().then(() => {
  console.log('Good to go!');
  done = true;
});

How does it work? If we expand it a bit:

它是如何工作的?如果我们稍微扩展一下:

// Initialize the variable `done` to `undefined`
// Create the function wait, which is available inside itself
// Note: `var` is hoisted but `let` is not so we need to use `var`
var done = (function wait () {

  // As long as it's nor marked as done, create a new event+queue
  if (!done) setTimeout(wait, 1000);

  // No return value; done will resolve to false (undefined)
})();

回答by vbarbarosh

Here is my two cents:

这是我的两分钱:

async function main()
{
    await new Promise(function () {});
    console.log('This text will never be printed');
}

function panic(error)
{
    console.error(error);
    process.exit(1);
}

// https://stackoverflow.com/a/46916601/1478566
main().catch(panic).finally(clearInterval.bind(null, setInterval(a=>a, 1E9)));

回答by Tushar

Please try this. Check if this help.

请试试这个。检查这是否有帮助。

var client = new mysql.Client(options);
console.log('Icanhasclient');
var verbose;

if (!verbose) {
    return new Promise(function (resolve, reject) {
        client.connect(function (err) {
            if (err) {
                console.log(Error in connecting
                SQL ${err}
            )
                ;
                return reject(err);
            }
            verbose = client;
            return resolve(verbose);
        })
    })
} else {
    return new Promise(function (resolve) {
        resolve(verbose);
    })
}

回答by exshovelrydr

I did look at felixge/node-mysqllibrary and didn't see a reference to the command client.connect in the API. Is this the actual call you're trying to make (not trying to be nitpicky here)? Regardless, IMHO you need to think more about how Javascript is designed, because it uses a programming paradigm different than most other popular languages.

我确实查看了felixge/node-mysql库,但在 API 中没有看到对命令 client.connect 的引用。这是您要拨打的实际电话吗(不要在这里挑剔)?无论如何,恕我直言,您需要更多地考虑 Javascript 的设计方式,因为它使用的编程范式与大多数其他流行语言不同。

The first issue I see in your code is that you haven't defined the callback, so it doesn't actually exist. I'd assume console.log(callback) is undefined. From your code, the anonymous function is the 'callback' for the client.connect function. You have to define what you are calling 'callback' at a higher scope. For example, I will define a function myCallback to exist in the scope higher than the client.connect's anonymous function. It may be useful to lookup Javacscript variable scope.

我在您的代码中看到的第一个问题是您尚未定义回调,因此它实际上并不存在。我假设 console.log(callback) 是未定义的。从您的代码中,匿名函数是 client.connect 函数的“回调”。您必须在更高的范围内定义您所说的“回调”。例如,我将定义一个函数 myCallback 存在于比 client.connect 的匿名函数更高的范围内。查找 Javascript变量范围可能很有用。

    var myCallback(err, response) {
      if (err) {
        console.log('err:%s',err);
      } else {
        console.log('response:%s',response);
      }
    }

    client.connect(err, function(response) {
      // this anonymous function is the callback to client.connect, the var
      // 'callback' would be undefined.
      if (err) {
        myCallback(err);
        return; // Explicit call to return, else the lines below would run.
      } 
      myCallback(null, response);
    });

Second, if you do not explicitly call return within Javascript, the function will continue to process. I was bitten by this myself. Finally, Javascript runs an event-drivenloop meaning it will never wait for functions to return a value, which is why we have all these callbacks in the first place. You can force Javascript to behave differently, for example by using a while loop until a condition is true. See the 'async' library by caolan, for various strategies of manipulating the event loop. The major disadvantage to overusing these methods is your actually wasting CPU cycles/blocking when you probably should use more callbacks and simply re-think how your programs works.

其次,如果您没有在 Javascript 中显式调用 return,该函数将继续处理。我自己也被这个咬了。最后,Javascript 运行一个事件驱动的循环,这意味着它永远不会等待函数返回值,这就是我们首先拥有所有这些回调的原因。您可以强制 Javascript 以不同的方式运行,例如通过使用 while 循环直到条件为真。有关操作事件循环的各种策略,请参阅caolan的“async”库。过度使用这些方法的主要缺点是您实际上浪费了 CPU 周期/阻塞,而您可能应该使用更多回调并简单地重新考虑您的程序如何工作。