Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Nothing is truly parallel in node.js since it is single threaded. However, multiple events can be scheduled and run in a sequence you can't determine beforehand. And some things like database access are actually "parallel" in that the database queries themselves are run in separate threads but are re-integrated into the event stream when completed.</p> <p>So, how do you schedule a callback on multiple event handlers? Well, this is one common technique used in animations in browser side javascript: use a variable to track the completion.</p> <p>This sounds like a hack and it is, and it sounds potentially messy leaving a bunch of global variables around doing the tracking and in a lesser language it would be. But in javascript we can use closures:</p> <pre><code>function fork (async_calls, shared_callback) { var counter = async_calls.length; var callback = function () { counter --; if (counter == 0) { shared_callback() } } for (var i=0;i&lt;async_calls.length;i++) { async_calls[i](callback); } } // usage: fork([A,B,C],D); </code></pre> <p>In the example above we keep the code simple by assuming the async and callback functions require no arguments. You can of course modify the code to pass arguments to the async functions and have the callback function accumulate results and pass it to the shared_callback function.</p> <hr> <h2>Additional answer:</h2> <p>Actually, even as is, that <code>fork()</code> function can already pass arguments to the async functions using a closure:</p> <pre><code>fork([ function(callback){ A(1,2,callback) }, function(callback){ B(1,callback) }, function(callback){ C(1,2,callback) } ],D); </code></pre> <p>the only thing left to do is to accumulate the results from A,B,C and pass them on to D.</p> <hr> <h2>Even more additional answer:</h2> <p>I couldn't resist. Kept thinking about this during breakfast. Here's an implementation of <code>fork()</code> that accumulates results (usually passed as arguments to the callback function):</p> <pre><code>function fork (async_calls, shared_callback) { var counter = async_calls.length; var all_results = []; function makeCallback (index) { return function () { counter --; var results = []; // we use the arguments object here because some callbacks // in Node pass in multiple arguments as result. for (var i=0;i&lt;arguments.length;i++) { results.push(arguments[i]); } all_results[index] = results; if (counter == 0) { shared_callback(all_results); } } } for (var i=0;i&lt;async_calls.length;i++) { async_calls[i](makeCallback(i)); } } </code></pre> <p>That was easy enough. This makes <code>fork()</code> fairly general purpose and can be used to synchronize multiple non-homogeneous events.</p> <p>Example usage in Node.js:</p> <pre><code>// Read 3 files in parallel and process them together: function A (c){ fs.readFile('file1',c) }; function B (c){ fs.readFile('file2',c) }; function C (c){ fs.readFile('file3',c) }; function D (result) { file1data = result[0][1]; file2data = result[1][1]; file3data = result[2][1]; // process the files together here } fork([A,B,C],D); </code></pre> <hr> <h2>Update</h2> <p>This code was written before the existence of libraries like async.js or the various promise based libraries. I'd like to believe that async.js was inspired by this but I don't have any proof of it. Anyway.. if you're thinking of doing this today take a look at async.js or promises. Just consider the answer above a good explanation/illustration of how things like async.parallel work.</p> <p>For completeness sake the following is how you'd do it with <code>async.parallel</code>:</p> <pre><code>var async = require('async'); async.parallel([A,B,C],D); </code></pre> <p>Note that <code>async.parallel</code> works exactly the same as the <code>fork</code> function we implemented above. The main difference is it passes an error as the first argument to <code>D</code> and the callback as the second argument as per node.js convention.</p> <p>Using promises, we'd write it as follows:</p> <pre><code>// Assuming A, B &amp; C return a promise instead of accepting a callback Promise.all([A,B,C]).then(D); </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload