I'm still learning a lot about how FBP and NoFlo works from a process perspective, so while I can hack something together that does the job, I'm unsure whether I'm introduce problems somewhere else.
In this case, I'm creating a component that waits for an input on each of its 2 ports before sending data to the out port. Why? I need data from both inputs to construct the output packet (group name and input packet).
I've managed to achieve this using 2 approaches and I'd like to know which approach is better, or at least the up/downsides to each approach.
The component I'm talking about here is vizicities/Group:
Approach 1: Queuing packets from input1 internally until the input2 has received a packet
var noflo = require("noflo");
exports.getComponent = function() {
var AddGroup = new noflo.Component();
AddGroup.description = "This component adds a group to the data packets";
var packets = [];
var groupName = "";
// Register ports and event handlers
AddGroup.inPorts.add("in", { datatype: "all" }, function(event, payload) {
switch (event) {
case "begingroup":
AddGroup.outPorts.out.beginGroup(payload);
break;
case "endgroup":
AddGroup.outPorts.out.endGroup();
break;
case "data":
// Queue packet
packets.push(payload);
break;
case "disconnect":
// Only send output if group has been set
if (groupName) {
for (var i = 0; i < packets.length; i++) {
AddGroup.outPorts.out.beginGroup(groupName);
AddGroup.outPorts.out.send(packets);
AddGroup.outPorts.out.endGroup();
}
// Disconnect output port when input port disconnects
AddGroup.outPorts.out.disconnect();
}
break;
}
});
AddGroup.inPorts.add("group", { datatype: "string" }, function(event, payload) {
switch (event) {
case "begingroup":
break;
case "endgroup":
break;
case "data":
groupName = payload;
break;
case "disconnect":
// TODO: Does this dupe anything with the same logic on the in port?
// Only send output if group has been set
if (groupName) {
for (var i = 0; i < packets.length; i++) {
AddGroup.outPorts.out.beginGroup(groupName);
AddGroup.outPorts.out.send(packets);
AddGroup.outPorts.out.endGroup();
}
// Disconnect output port when input port disconnects
AddGroup.outPorts.out.disconnect();
}
break;
}
});
AddGroup.outPorts.add("out", { datatype: "all" });
return AddGroup; // Return new instance
};
Approach 2: Using the WirePattern helper
var noflo = require("noflo");
exports.getComponent = function() {
var AddGroup = new noflo.Component();
AddGroup.description = "This component adds a group to the data packets";
var config = {
in: ["in", "group"],
out: "out"
};
AddGroup.inPorts = new noflo.InPorts({
in: {
datatype: "string",
required: true
},
group: {
datatype: "string",
required: true
}
});
AddGroup.outPorts = new noflo.OutPorts({
out: {
datatype: "all"
}
});
noflo.helpers.WirePattern(AddGroup, config, function(data, groups, outPort) {
outPort.beginGroup(data.group);
outPort.send(data.in);
outPort.endGroup();
});
// Return new instance
return AddGroup;
};
Both approaches seem to work, though clearly there must be a reason for using one over the other. Can someone clarify this for me?
WirePattern is the recommended way in modern NoFlo, as it provides you with additional control on packet synchronization when needed. You can fire when all the required inputs get data, or you can require a strict group (or even packet payload) matches.
A lot of common NoFlo components are still waiting for WirePattern-ization, but for anything new, and even more so for anything asynchronous it is the recommended way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With