Ports
Port data types
NoFlo is a flow-based programming environment for JavaScript, and JavaScript utilizes dynamic typing. Because of this, NoFlo component ports don't impose type safety, and the output of any port can be connected to the input of any other port. This means that any type checking or type conversions should be handled inside the components themselves.
To aid users in designing graphs, it is however possible to annotate ports with the data type they expect to receive or transmit. This data type is given as a string value of the datatype
attribute when adding a port to a component. For example:
component.inPorts.add 'in', datatype: 'string'
component.inPorts.add 'options', datatype: 'object'
The data types supported by NoFlo include:
- all: the port can deal with any data type
- bang: the port doesn't do anything with the contents of a data packet, only with the fact that a packet was sent, so any datatype can be sent to a bang port
- string
- boolean
- number
- int
- object
- array
- color
- date
- function
- buffer
- stream
Port Attributes
There is a set of other attributes a port may have apart from its datatype
:
addressable
: this boolean flag makes turns the port into an Array port, giving a particular index for each connection attached to it (default:false
); Array ports have a third value on events with the socket index:
@inPorts.in.on 'data' , (event, payload, index ) -> ...
cached
: this option makes an output port re-send last emitted value when new connections are established (default:false
);datatype
: string type name of data the port accepts, see above (default:all
);description
: provides human-readable description of the port displayed in documentation and in Flowhub inspector;required
: indicates that a connection on the port is required for component's functioning (default:false
);values
: sets the list of accepted values for the port, if the value received is not in the list an error is thrown (default:null
).control
: ports can be used to keep whatever the last packet that was sent to it. They only keep data and they silently drop brackets. (default:false
)triggering
: this boolean flag is useful to set astriggering: false
on acontrol
port where the data should be stored, but theprocess
handler should not be triggered/called when data comes into that port. (default:true
)
Here is how multiple attributes can be declared:
component.inPorts.add 'id',
datatype: 'int'
description: 'Request ID'
component.inPorts.add 'user',
datatype: 'object'
description: 'User data'
This can alternatively be done using constructors explicitly:
noflo = require 'noflo'
component.inPorts = new noflo.inPorts
in:
datatype: 'int'
description: 'Request ID'
user:
datatype: 'object'
description: 'User data'
The third way this can be done is passing in the ports as objects to the component constructor.
c = new noflo.Component
icon: 'gear'
inPorts:
eh:
datatype: 'all'
required: true
outPorts:
canada:
datatype: 'object'
required: true
error:
datatype: 'object'
Sockets
The default communications mechanism between NoFlo processes is an internal socket, which is responsible for accepting information packets sent from processes' outports, and emitting corresponding events so that the packets can be subscribed to by the inport of the connected process.
Sockets attach to a port, become connected (their connected
property becomes true
), receive data, translate if needed, send data, then when they are done sending, become disconnected (their connected
property becomes false
).
Sending
When manually instantiating and attaching sockets, there are two ways to send packets. Behind the scenes, outport sending methods use them.
Sending information packets
The send method is used by a processes outport to send information packets. The actual packet contents are not defined by NoFlo, and may be any valid JavaScript data structure.
The packet contents however should be such that may be safely serialized or deserialized via JSON. This way the NoFlo networks can be constructed with more flexibility, as file buffers or message queues can be used as additional packet relay mechanisms.
send: (data) ->
Sending information packets without open bracket
As connect event is considered as open bracket, it needs to be followed by a disconnect event or a closing bracket. In the new simplified sending semantics single IP objects can be sent without open/close brackets.
post: (ip, autoDisconnect = true) ->