Starting out with noflo, running it from nodejs

2019-04-10 22:55发布

问题:

I got a simple noflo example running from noflo. But I'm having no luck figuring out how noflo should work with node and other code.

At first I had this fbp file:

# In the graph we first need to define the nodes and the connections between them
Read(filesystem/ReadFile) OUT -> IN Display(core/Output)

# Start off the graph by sending a filename to the file reader
#'package.json' -> IN Read

I tried: noflo.loadFile(filepath, nodedir, function(graph)

This works and prints to the console. But if I omit the last line in the fbp, that feeds the package.json parameter, I found no way of running the graph.

Is there a guide somewhere on how to use noflo from nodejs code and not from command-line?

回答1:

Typically NoFlo components don't do anything before they receive some input, in this case the file path to read from. From NoFlo component docs:

A running instance of a component in a NoFlo network is called a process. Before a process has received data it should be inert, merely listening to its input ports. Processes that need to start doing something when a network is started should be triggered to do so by sending them an Initial Information Packet.

The last line in your .fbp graph definition is sending the string package.json to the ReadFile component.

You can also do this programmatically after you've loaded the file into a NoFlo network:

noflo.loadFile(filepath, process.cwd(), function (network) {
  // Now we have access to the NoFlo network instance

  // Add Initial Information Packet programatically
  network.graph.addInitial(someFileToRead, 'Read', 'in');

  // Tell NoFlo to send the new IIPs
  network.sendInitials();
});

Exported ports and subgraphs

Now, there is also a more elegant way to do this, by exposing your .fbp file as a graph in NoFlo's ComponentLoader and then interacting with it as you'd interact with any other component.

To make the ports you're interested in available from the outside, you need to export them. In this case at least the ReadFile IN port from the graph. This would change your network definition to:

# Export the filename port so it can be accessed from outside
INPORT=Read.IN:FILENAME

# The rest of the graph definition follows
Read(filesystem/ReadFile) OUT -> IN Display(core/Output)

(as it happens, this is exactly the example I was using on exported ports in the .fbp language definition)

To make your graph available as a component you need to save it to inside your Node.js project (convention is the graphs/ subdirectory) and register it in the package.json file:

{
  "noflo": {
    "graphs": {
      "MyGraph": "graphs/MyGraph.fbp"
    }
  }
}

Now you can treat it as any other component. For example:

var loader = new noflo.ComponentLoader(__dirname);
loader.load('MyGraph', function (instance) {
  // The instance is a running NoFlo subgraph with your graph definition

  // Create a socket and attach it to the exported port
  var filename = noflo.internalSocket.createSocket();
  instance.inPorts.filename.attach(filename);

  filename.send(someFileToRead);
  filename.disconnect();
});

One reason why this is the preferred method is that you can not only use this to send IIPs, but also to attach sockets to the exported output ports and listen events on them. This way you can easily utilize any NoFlo graphs as asynchronous functions in your JavaScript application.



标签: node.js noflo