1

So, I am trying to make sure that a series of HTTP GET requests happen before I try to render the data gotten into a visualization. Typical deal, right?

I'm using queue.js, and seeing this on the queue.js github page (https://github.com/mbostock/queue):

Or, if you wanted to run a bazillion asynchronous tasks (here represented as an array of closures) serially:

    var q = queue(1);
    tasks.forEach(function(t) { q.defer(t); });
    q.awaitAll(function(error, results) { console.log("all done!"); });

Queue.js can be run inside Node.js or in a browser.

So, what I did was made an array of functions, each of which contained a Meteor.http.get call (as I'm using Meteor.js) and then followed this line by line.

It seems like what is happening is that while my array -- which has 8 functions in it, all with what looks like the right function in each slot -- gets populated (and then passed as in the code exceprt to defer,) only one actually runs.

Here's what I'm wondering. Well, overall it's, why is only one function running though 8 are passed in to defer? But specifically it's -- having a hazy understanding of closures, I really have an array of functions. Is there something I missed there, since the documentation specifically says closures, which is why all the functions aren't executing?

Thank you for looking at this!

4
  • You should use a Deferred or Promise for that. See Common.js and jQuery for proposals and implementations. (And of course now I notice that is a deferred.) Commented Mar 23, 2013 at 0:14
  • Also, it would help quite a bit if you included the code you describe, including the invocation context of the queue and any other relevant details. How you work a deferred in practice helps to understand the problem. Commented Mar 23, 2013 at 0:20
  • 1
    All closures in JavaScript are functions: a closure is simply a function that "closes over" (or "binds to") a variable in an outer lexical scope. The title makes no sense. Commented Mar 23, 2013 at 0:21
  • 1
    @pst - Note the OP is merely quoting Mike Bostock's example which of course quotes directly as (here represented as an array of closures) serially. I think it's a logical question to ask, what the heck does that mean? Commented Mar 23, 2013 at 0:25

1 Answer 1

1

Here is perhaps the literal part of the statement you quoted, found in the test suite:

"queue of asynchronous closures, processed serially": {
    topic: function() {
        var tasks = [], 
            task = asynchronousTask(),
            n = 10,
            q = queue(1);

        while (--n >= 0) tasks.push(task);

        tasks.forEach(function(t) { q.defer(t); });

        q.awaitAll(this.callback)
    },
    "does not fail": function(error, results) {
        assert.isNull(error);
    },
    "executes all tasks in series": function(error, results) {
        assert.deepEqual(results, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]);
    }
},

https://github.com/mbostock/queue/blob/master/test/queue-test.js#L103

Which runs task = asynchronousTask(), which is what is pulled off the queue and invoked

function asynchronousTask() {
    var active = 0;

    return function(callback) {
        ++active;

        process.nextTick(function() {
            try {
                callback(null, active);
            } finally {
              --active;
            }
        });
    };
}

The above, inner return function() {...} is what I believe is being referenced as a closure which retains it's reference in scope to the outer active variable as each asynchronous function is called off the queue.

This is, of course, fairly powerful in terms of callbacks and handlers, since it gives you the means to maintain and manipulate a locally shared variable, for instance if you want to know how many functions were returned, and when the list has been exhausted. In other words, a queue.

The following is not used in the example up top, but use it as a reference point to see how it differs from the synchronousTask function above.

function synchronousTask() {
    var active = 0;

    return function(callback) {
        try {
            callback(null, ++active);
        } finally {
            --active;
        }
    };
}

https://github.com/mbostock/queue/blob/master/test/queue-test.js#L265

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.