将变量传递给Node.js中的回调

时间:2021-11-10 16:23:52

I'm quite new to node and am trying to create something that gets some server info. But here's my problem. I setup a config object (this will, in time, become updated dynamically by events that occur) and then later in, in a function, I try and access a value in this object. (See code below)

我对节点很新,我正在尝试创建一些获取服务器信息的东西。但这是我的问题。我设置了一个配置对象(这将及时,由发生的事件动态更新),然后在函数中,我尝试访问该对象中的值。 (见下面的代码)

So First, I setup my vars:

首先,我设置我的变量:

var util            = require('util'),
    child           = require('child_process'),
    config          = {};

which works okay. Then I load my config:

这没关系。然后我加载我的配置:

function loadConfig( )
{
    // Add some code for auto-loading of args
    config = {
        "daemons": [
            ["Apache", "apache2"],
            ["MySQL",  "mysqld"],
            ["SSH", "sshd"]
        ]
    };
}

and init that calling the function

并初始化调用该函数

loadConfig();

After that, I run my check on daemons.

之后,我对守护进程进行检查。

function getDaemonStatus( )
{
    for(var i=0; i<config.daemons.length; i++)
    {

        child.exec( 'ps ax -o \'%c %P\' | awk \'{if (($2 == 1) && ($1 == "\'' +
            config.daemons[i][1] + '\'")) print $0}\'',
            function( error, stdout, stderr )
        {

            console.log(config.daemons[i]);
        });
    }
}

The response I get is:

我得到的回应是:

undefined
undefined
undefined

I don't really want to use a GLOBAL variable, so can you guys think of another way to solve my problem?

我真的不想使用GLOBAL变量,所以你们想到另一种方法来解决我的问题吗?

Thanks! =]

谢谢! =]

1 个解决方案

#1


13  

This is a gotcha that lots of people run into because of the asynchronous ordering of execution.

由于执行的异步排序,这是很多人遇到的问题。

Your for loop will look from 0-3, and then exit when 'i' is four, obviously. The tough part to remember here is that your callback for exec won't run immediately. In only runs once the process has started, and by the time that happens, the for loop will be done.

您的for循环将从0-3开始,然后当'i'为4时退出,显然。这里要记住的难点是你的exec回调不会立即运行。仅在进程启动后运行,并且在发生的时间,for循环将完成。

That means that essentially, all three times that your callback function is running, you are essentially doing this:

这意味着,基本上,你的回调函数运行的所有三次,你基本上这样做:

console.log(config.daemons[4]);

That's why it prints 'undefined'.

这就是它打印'undefined'的原因。

You need to capture the 'i' value in a new scope, by wrapping the loop contents in an anonymous, self-executing function.

您需要通过将循环内容包装在匿名的自执行函数中来捕获新范围中的“i”值。

function getDaemonStatus( ) {
    for(var i=0; i<config.daemons.length; i++) {
        (function(i) {

             child.exec( 'ps ax -o \'%c %P\' | awk \'{if (($2 == 1) && ($1 == "\'' +
                config.daemons[i][1] + '\'")) print $0}\'',
                function( error, stdout, stderr ) {

                console.log(config.daemons[i]);
            });

        })(i);
    }
}

Also, I see that your function is called 'getDaemonStatus'. Just remember that, since that exec callback is asyncronous, that also means that you can't collect the results of each callback, and then return them from the getDaemonStatus. Instead, you will need to pass a your own callback, and call the it from inside your exec callback.

另外,我看到你的函数被称为'getDaemonStatus'。请记住,由于该exec回调是异步的,这也意味着您无法收集每个回调的结果,然后从getDaemonStatus返回它们。相反,您需要传递一个自己的回调,并从您的exec回调中调用它。

Updated

Note though, the easiest way to have a scope per-iteration is to use forEach, e.g.

但请注意,每次迭代使用范围的最简单方法是使用forEach,例如

function getDaemonStatus( ) {
    config.daemons.forEach(function(daemon, i){
         child.exec( 'ps ax -o \'%c %P\' | awk \'{if (($2 == 1) && ($1 == "\'' +
            daemon[1] + '\'")) print $0}\'',
            function( error, stdout, stderr ) {

            console.log(daemon);
        });
    }
}

#1


13  

This is a gotcha that lots of people run into because of the asynchronous ordering of execution.

由于执行的异步排序,这是很多人遇到的问题。

Your for loop will look from 0-3, and then exit when 'i' is four, obviously. The tough part to remember here is that your callback for exec won't run immediately. In only runs once the process has started, and by the time that happens, the for loop will be done.

您的for循环将从0-3开始,然后当'i'为4时退出,显然。这里要记住的难点是你的exec回调不会立即运行。仅在进程启动后运行,并且在发生的时间,for循环将完成。

That means that essentially, all three times that your callback function is running, you are essentially doing this:

这意味着,基本上,你的回调函数运行的所有三次,你基本上这样做:

console.log(config.daemons[4]);

That's why it prints 'undefined'.

这就是它打印'undefined'的原因。

You need to capture the 'i' value in a new scope, by wrapping the loop contents in an anonymous, self-executing function.

您需要通过将循环内容包装在匿名的自执行函数中来捕获新范围中的“i”值。

function getDaemonStatus( ) {
    for(var i=0; i<config.daemons.length; i++) {
        (function(i) {

             child.exec( 'ps ax -o \'%c %P\' | awk \'{if (($2 == 1) && ($1 == "\'' +
                config.daemons[i][1] + '\'")) print $0}\'',
                function( error, stdout, stderr ) {

                console.log(config.daemons[i]);
            });

        })(i);
    }
}

Also, I see that your function is called 'getDaemonStatus'. Just remember that, since that exec callback is asyncronous, that also means that you can't collect the results of each callback, and then return them from the getDaemonStatus. Instead, you will need to pass a your own callback, and call the it from inside your exec callback.

另外,我看到你的函数被称为'getDaemonStatus'。请记住,由于该exec回调是异步的,这也意味着您无法收集每个回调的结果,然后从getDaemonStatus返回它们。相反,您需要传递一个自己的回调,并从您的exec回调中调用它。

Updated

Note though, the easiest way to have a scope per-iteration is to use forEach, e.g.

但请注意,每次迭代使用范围的最简单方法是使用forEach,例如

function getDaemonStatus( ) {
    config.daemons.forEach(function(daemon, i){
         child.exec( 'ps ax -o \'%c %P\' | awk \'{if (($2 == 1) && ($1 == "\'' +
            daemon[1] + '\'")) print $0}\'',
            function( error, stdout, stderr ) {

            console.log(daemon);
        });
    }
}