简体   繁体   中英

JavaScript Callbacks and Splunk

I am in the process of using the Splunk Javascript API to gain access to some of its functionality, but I'm having trouble understanding JavaScript concepts behind callbacks.

An example from the docs:

var http = new splunkjs.ProxyHttp("/proxy");
var service = new splunkjs.Service(http, {
    username: username,
    password: password,
    scheme: scheme,
    host: host,
    port: port,
    version: version
});

Async.chain([
        // First, we log in
        function(done) {
            service.login(done);
        },
        // Perform the search
        function(success, done) {
            if (!success) {
                done("Error logging in");
            }

            service.search("search index=_internal | head 3", {}, done);
        },
        // Wait until the job is done
        function(job, done) {
            Async.whilst(
                // Loop until it is done
                function() { return !job.properties().isDone; },
                // Refresh the job on every iteration, but sleep for 1 second
                function(iterationDone) {
                    Async.sleep(1000, function() {
                        // Refresh the job and note how many events we've looked at so far
                        job.fetch(function(err) {
                            console.log("-- fetching, " + (job.properties().eventCount || 0) + " events so far");
                            iterationDone();
                        });
                    });
                },
                // When we're done, just pass the job forward
                function(err) {
                    console.log("-- job done --");
                    done(err, job);
                }
            );
        },
        // Print out the statistics and get the results
        function(job, done) {
            // Print out the statics
            console.log("Job Statistics: ");
            console.log("  Event Count: " + job.properties().eventCount);
            console.log("  Disk Usage: " + job.properties().diskUsage + " bytes");
            console.log("  Priority: " + job.properties().priority);

            // Ask the server for the results
            job.results({}, done);
        },
        // Print the raw results out
        function(results, job, done) {
            // Find the index of the fields we want
            var rawIndex        = utils.indexOf(results.fields, "_raw");
            var sourcetypeIndex = utils.indexOf(results.fields, "sourcetype");
            var userIndex       = utils.indexOf(results.fields, "user");

            // Print out each result and the key-value pairs we want
            console.log("Results: ");
            for(var i = 0; i < results.rows.length; i++) {
                console.log("  Result " + i + ": ");
                console.log("    sourcetype: " + results.rows[i][sourcetypeIndex]);
                console.log("    user: " + results.rows[i][userIndex]);
                console.log("    _raw: " + results.rows[i][rawIndex]);
            }

            // Once we're done, cancel the job.
            job.cancel(done);
        }
    ],
    function(err) {
        callback(err);        
    }
);

Async.chain is defined here as being root.chain = function(tasks, callback) . My understanding is that there are 5 functions in the tasks array which are executed one after the other, and pass the results from one to the other.

However I do not understand how and where "done", "success","job" and "results" are defined, or how it is that they are used as arguments within the body of their functions?

  function(success, done) {
            if (!success) {
                done("Error logging in");
            }

            service.search("search index=_internal | head 3", {}, done);
  }

here, how is it testing against success, and passing a string to done()?

and how does the two functions

function(job, done) {// Print out the statics ..}
&
function(results, job, done) { .. }

pass the results data from the first function to the second?

Apologies for the long question.

In Javascript, functions create new scope. That means it does not matter what the passed arguments were named before they were passed to the function.

var awesomeName = 'bob';

hi(awesomeName);

// name === undefined

function hi(name) {
    // name === 'bob';
    console.log('hi', name); // Outputs: 'hi bob' in console
}

// name === undefined

As you said, each task calls the next task as a callback. The last argument is always the next task function/callback . That means that Async.chain probably automagically adds the callbacks to the end of the arguments before calling each task function. done is just a conventional name to assign to the callback. Similarly, the other arguments are just descriptive names for the arguments passed by the previous task. In order to see why they are named that way, you should look at the function that is calling the callback.

For example:

service.login(done) probably has some kind of code in it that does something like this:

login: function(callback) {
    var successful;

    // Do Login logic here and assign true/false to successful

    callback(successful);
}

The callback is the next task in the chain and has two arguments, success and done . success is just the first argument that login passed to it. Async.chain always passes another argument as the last argument: the next task function, which is just assigned the name done by convention. You could name it whatever you want within each function, as long as you refer to it as the same name within the function.

function cb(success, fuzzyCallback) {
  if (!success) {
    fuzzyCallback('Error!');
  }

  fuzzyCallback(null);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM