This example finds all files in a specified directory, opens each and counts the number of lines of text contained. The example is contrived to use two state machines, countLines and counter, to illustrate how the spawn plug-in is used.

The counter state machine is responsible for counting the number of lines in a single file. Its ReadFile state uses an asynchronous guard function to check that the path it receives is a file path and if so reads the files and passes its data to CountLines. This state uses the work plug-in to perform the counting process asynchronously.

The countLines state machine has two states, ReadDir and Spawn. ReadDir reads the target directory and passes its contents in an array to Spawn. This state starts a new counter state machine to perform the line counting process for each file. Notice that the state loops back on itself until the array is empty. It then waits until the 'CounterSpawner.quiet' event is received, indicating that all spawned counter state machine have exited.

var path = require('path');

function counter (fire, filePath) {
  this.startState = 'ReadFile';

  this.states = {
    ReadFile: {
      guard: {
        async: 'fs.stat',
        actions: {
          'async.done': function (stat) {
            if (!stat.isFile()) {
              return '@exit';
            }
          },
          'async.err': '@exit'
        }
      },
      async: 'fs.readFile',
      actions: {
        '.done': 'CountLines',
        '.err': '@exit'
      }
    },

    CountLines: {
      work: function (data) {        
        console.log('%s has %d lines', filePath, 
            String(data).split('\n').length);
        return [ 'done' ];
      },
      actions: {
        '.done': '@exit'
      }
    }
  };
};

function countLines (fire, dir) {
  this.startState = 'ReadDir';
  this.states = {
    ReadDir: {
      entry: function () {
        fire.$spawner('CounterSpawner', counter);
        fire.fs.readdir(dir) ;
      },
      actions: {
        '.done': 'Spawn',
        '.err': '@error'
      }
    },

    Spawn: {
      spawn: {
        factory: 'CounterSpawner',
        smArgs: function (files) {
          return path.join(dir, files.shift());
        }
      },
      actions: {
        '.done': function (files) {
          if (files.length) {
            return '@self';
          }
        },
        'CounterSpawner.quiet': '@exit'
      }
    }
  };
};

countLines.defaults = {
    imports: { fs: require('fs') },
    args: ['.']
};

module.exports = countLines;

Example Output

The source code for the example can be found in the file examples/plugins/spawn/count_lines.js and run using the ignite command line helper application as follows:

 $ ./bin/ignite examples/plugins/spawner/count_lines.js
 Running examples/plugins/spawn/count_lines.js
 index.js has 8 lines
 .project has 23 lines
 package.json has 57 lines
 todo.md has 57 lines
 .gitignore has 8 lines
 bsd3.txt has 27 lines
 .npmignore has 8 lines
 run: examples/plugins/spawn/count_lines.js Exited with no error.
 $_

See