# Sub-flows. I am missing something in how they work

**URL:** <https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910>\
**Category:** General\
**Created:** [20 October 2019 02:47 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910 "2019-10-20T02:47:23Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [20 October 2019 02:47 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/1 "2019-10-20T02:47:23Z")

</div>

Sorry, but this has me stumped.

I have/had a bunch of nodes which were painful for me to maintain and so I made a _subflow_ of them.

Heaps easier to roll out updates to them. Rather than having to edit them all, I just edit the subflow and all is sweet.

Thing is it isn't.

I have most of them devices using the subflow to determine their condition, and most of them are content. Showing "online-responding" every pulse. (About 20 seconds)

Alas one of the devices decides to (now and then) become cantankerous every now and then and every other pulse, shows "booting" condition. Every alternative to that it shows as "online-responding".

So something is _not happening_ in there to cause that.

If I re-wire the actual nodes into the flow, this behaviour stops.

But they are the same nodes as those in the subflow.

Any ideas what I can do to try and work out what is going on?

There are 2 other devices connected using the same subflow and they are happy as. No "booting" signal every alternate pulse.

(And typically: Now that I posted this question it has decided to behave itself.)

I don't want to just dump the flow here. It is complicated and you need to understand what it is doing.

I can write out what happens and post it, but I thought it would be polite to first ask for ideas on how to see what is going on where it is only happening with one (of three) devices connected and all are using the same subflow.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [20 October 2019 03:03 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/2 "2019-10-20T03:03:06Z")

</div>

Are you using flow or global context inside the sub flow? I.e. you could have concurrency issues)

Are you processing object sent in (i.e. perhaps you have a reference object being modified asynchronously)

Have you added debug nodes before and after to capture the input and output and verified the node isn't behaving accordingly (i.e. "shit in, shit out" scenario)

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [20 October 2019 03:15 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/3 "2019-10-20T03:15:33Z")

</div>

Well. . . . . .

I went about making the subflow the wrong way. In that:

rather than make the subflow to do something I was doing it all with nodes.

When they all worked, I copied them and pasted them in the new location. Set a couple of things differently and it worked.

This was (but not originally) painful if I found a bug. I had to go through the process of editing all the nodes.

Going through the code in one (of 3) function nodes I have this line.  
`var debug = flow.get(device+'_Button_Debug') || false; // if active: true`  
Though not directly responsible for the problem, it uses `flow.get` from when it was not a subflow.

Will this cause problems? (New ones to which I haven't even got yet)

Most of the stuff is all just `context.get/set( )` stuff. Though I have to admit, that is a `flow.get( )` example.

Otherwise all variables are `context.get/set( )`

Just did a check. There is only the one `flow.get( )` used. That is for debugging - as was indicated in the code.

So really it is all just simple `context.get/set( )` stuff.

(I feel like I am repeating myself. Not intended.)

So I think I am meaning that I have kind of passed the shit in/shit out scenario because if it was true, none of the other two devices would work.

Also as I mentioned: It is intermittent. It was happening when I posted and as I was posting, it stopped. That is to say I was starting to re-wire the nodes to the "real" nodes (as opposed to the subflow) and it started to behave itself.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [20 October 2019 03:43 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/4 "2019-10-20T03:43:08Z")

</div>

> [@Trying\_to\_learn](#):
>
> Though not directly responsible for the problem, it uses `flow.get` from when it was not a subflow.
> 
> Will this cause problems? (New ones to which I haven't even got yet)

Reading a flag from flow context for debug is fine.

It's when you store a value in flow/global in a subflow, all instances of the subflow are doing the same thing. Potentially at the same time, interfering with each other.

As for node context.set/get, I have to be honest here - I'm not certain how subflow nodes are instansiated.

In my mind, context store is kinda like a class property - in that each instance had its own unique variable. But a node in a sub flow - I'm just not certain. My guess is context storage on a node inside a subflow is unique to each instance (and therefore safe) however I'm not 100% certain.  
Without nick or Dave to quickly answer, we could perform a little test could help us understand.

Create a subflow with 1 function node...

Subflow...  
In --\> function--\>out

```auto
var time = context.get("time");
if(!time){
  time=Date.now();
  context.set("time", time);
}
msg.payload = time;
return msg;

```

Then put 2 instances of the subflow on a flow...

- Inject-subflow-debug
- Inject-subflow-debug

If you click the 1st inject then wait a second then press the 2nd inject, do you get the same timestamp or a different timestamp?

A different timestamp means node context in a subflow is it's own variable and therefore safe (IE multiple subflow instances won't interfere with each other)

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [20 October 2019 03:51 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/5 "2019-10-20T03:51:29Z")

</div>

Only 1 output. 🙂

I'll spare you the screen shot.

So that looks good for that.

`context.get/set( )` is local to that instance of the iteration of the subflow.

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [20 October 2019 03:53 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/6 "2019-10-20T03:53:38Z")

</div>

As it is so intermittent I won't lose too much sleep on it.

I probably stuffed up somewhere. As I usually do.

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [20 October 2019 04:10 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/7 "2019-10-20T04:10:09Z")

</div>

Just to test the idea, this is what I _know_ about the topic:

> The nodes in a subflow can use flow context, but it is scoped to the nodes in the subflow, not the flow the instance of the subflow is on.

> If you are on 0.20, then the nodes in the subflow can access the parent flow context. If you have a flow context variable called foo then the nodes in a subflow can use $parent.foo to access it.

I made this flow:  
(Well, sub flow actually)

```auto
[{"id":"d03cee5c.debbf","type":"subflow","name":"Subflow 2","info":"","in":[{"x":220,"y":100,"wires":[{"id":"b6a05627.03a81"}]}],"out":[{"x":560,"y":100,"wires":[{"id":"b6a05627.03a81","port":0}]}]},{"id":"b6a05627.03a81","type":"function","z":"d03cee5c.debbf","name":"","func":"var x = flow.get($parent.test);\nmsg.payload = x;\nreturn msg;","outputs":1,"noerr":0,"x":360,"y":100,"wires":[[]]}]

```

That is a sub-flow.

I set this up:

```auto
[{"id":"d03cee5c.debbf","type":"subflow","name":"Subflow 2","info":"","in":[{"x":220,"y":100,"wires":[{"id":"b6a05627.03a81"}]}],"out":[{"x":560,"y":100,"wires":[{"id":"b6a05627.03a81","port":0}]}]},{"id":"b6a05627.03a81","type":"function","z":"d03cee5c.debbf","name":"","func":"var x = flow.get($parent.test);\nmsg.payload = x;\nreturn msg;","outputs":1,"noerr":0,"x":360,"y":100,"wires":[[]]},{"id":"9ea5acd.d1ad25","type":"debug","z":"accbdb61.d75918","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":580,"y":760,"wires":[]},{"id":"69a06ac9.813d24","type":"inject","z":"accbdb61.d75918","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":760,"wires":[["f6961980.dfd6d"]]},{"id":"f6961980.dfd6d","type":"subflow:d03cee5c.debbf","z":"accbdb61.d75918","name":"","x":340,"y":760,"wires":[["9ea5acd.d1ad25"]]},{"id":"26a16337.fdde04","type":"inject","z":"accbdb61.d75918","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":620,"wires":[["37c662d1.dc05ae"]]},{"id":"37c662d1.dc05ae","type":"change","z":"accbdb61.d75918","name":"","rules":[{"t":"set","p":"test","pt":"flow","to":"ONE","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":310,"y":620,"wires":[[]]},{"id":"f43ae422.a4c","type":"change","z":"accbdb61.d75918","name":"","rules":[{"t":"set","p":"test","pt":"flow","to":"TWO","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":310,"y":670,"wires":[[]]},{"id":"79938c3d.d2cf7c","type":"inject","z":"accbdb61.d75918","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":670,"wires":[["f43ae422.a4c"]]}]

```

I don't get to see "ONE" or "TWO" come out of the `debug` node if I set it with either of the top `inject` nodes.

But I can see the `flow context` variable if I look at it with the `context data` option.

So I'm missing something here.

---

<div class="post-metadata">

**Author:** ![krambriw](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/krambriw/32/5429_2.png) [@krambriw](https://discourse.nodered.org/u/krambriw)\
**Post date:** [20 October 2019 06:52 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/8 "2019-10-20T06:52:08Z")

</div>

> [@Trying\_to\_learn](#):
>
> `context.get/set( )` is local to that instance of the iteration of the subflow

The same seems valid for flow.get/set (just modify Steves time example and try). But changing it to global you will see they will operate on the same variable that is not kept inside each instance of the  
subflows, i.e. it is instead in the global context

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [20 October 2019 08:19 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/9 "2019-10-20T08:19:32Z")

</div>

(Idiot hat on)

Sorry. I'm not getting what you mean.

To break it down to the node in the subflow, this is what I have - NOT working:

```auto
node.warn("Message received"); // for the sake of knowing the message arrived
var x = flow.get($parent.test);
msg.payload = x;
return msg;

```

Though I think line 2 is the problem.

So the flow context (from the "parent" flow) I want to get is called test.

I did it as explained from Nick (other thread a while ago), but I am (obviously) missing something.

For the sake of my learning can you _show_ me what that code needs to be?

---

<div class="post-metadata">

**Author:** ![craigcurtin](https://avatars.discourse-cdn.com/v4/letter/c/94ad74/32.png) [@craigcurtin](https://discourse.nodered.org/u/craigcurtin)\
**Post date:** [20 October 2019 08:38 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/10 "2019-10-20T08:38:51Z")

</div>

What they are trying to say is that if you EXPLICITLY name the variable/context (GLobal or Flow) then each time the subflow runs it will only access that named instance - regardless of where you call it from - this would be desireable if the subflow was not called concurrently by many flows.

On the other hand if you were to call it concurrently from many flows then you will want each instance of the subflow variables to be instantiated and unique to that calling iteration until the parent process dies - otherwise they will be trampling all over each other

Craig

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [20 October 2019 08:50 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/11 "2019-10-20T08:50:56Z")

</div>

I appreciate the reply Craig, but I am still not getting it.

I have (again keeping it in line with what is already said) in the flow I set a flow variable `test` to something. (String)

At any time the sub-flow is called and needs to get the value of `test` from the parent flow.

But I am still not seeing a working way of doing this.

I think the brain is really not working just now. ☹

---

<div class="post-metadata">

**Author:** ![krambriw](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/krambriw/32/5429_2.png) [@krambriw](https://discourse.nodered.org/u/krambriw)\
**Post date:** [20 October 2019 09:07 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/12 "2019-10-20T09:07:25Z")

</div>

> [@Trying\_to\_learn](#):
>
> But I am still not seeing a working way of doing this

Just to be clearer, that is something I did not respond to, I do not know how you can grab flow data from the parent. Only thing I noticed during my tests is that you can get global data in the same way as usual but context and flow data stays local in the sub flow

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [20 October 2019 09:10 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/13 "2019-10-20T09:10:05Z")

</div>

No problems. I'm not saying you had to answer.

I'm just confused that I have read how to do it, but what is written doesn't work, or: I am doing something wrong.

Just looking for what the correct way of doing it is.

---

<div class="post-metadata">

**Author:** ![bakman2](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bakman2/32/6207_2.png) [@bakman2](https://discourse.nodered.org/u/bakman2)\
**Post date:** [20 October 2019 09:22 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/14 "2019-10-20T09:22:38Z")

</div>

> [@Trying\_to\_learn](#):
>
> var x = flow.get($parent.test);

Not sure where this comes from, but I can imagine that a subflow is not part of the flow it is living in (it's in its' own little world), in terms of context.

Instead of trying to read the flow variable in the subflow, why not just inject it into the subflow node with a payload property ? You have to inject payloads anyway.

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [20 October 2019 09:28 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/15 "2019-10-20T09:28:42Z")

</div>

I see Nick is replying, but just to set the records straight:

[Where I got the information](https://discourse.nodered.org/t/subflow-context-flow/11534)

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [20 October 2019 09:29 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/16 "2019-10-20T09:29:05Z")

</div>

Assuming to you want to access the flow context variable called `test` in the flow containing your subflow instance node, then

```auto
var x = flow.get($parent.test);

```

Should be

```auto
var x = flow.get("$parent.test")

```

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [20 October 2019 09:30 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/17 "2019-10-20T09:30:59Z")

</div>

> [@Trying\_to\_learn](#):
>
> Though I think line 2 is the problem.

You need quotes around the text otherwise it thinks $parent2.test is a local variable it needs to evaluate and already not the value of a variable.

```auto
[{"id":"a11d54.726bd2b","type":"subflow","name":"Subflow 1","info":"","in":[{"x":60,"y":80,"wires":[{"id":"63e10fae.b1efd"}]}],"out":[{"x":320,"y":80,"wires":[{"id":"63e10fae.b1efd","port":0}]}],"status":{"x":320,"y":160,"wires":[{"id":"63e10fae.b1efd","port":0}]}},{"id":"63e10fae.b1efd","type":"function","z":"a11d54.726bd2b","name":"","func":"node.warn(\"Message received\"); // for the sake of knowing the message arrived\nmsg.payload = flow.get(\"$parent.test\");\nreturn msg;","outputs":1,"noerr":0,"x":190,"y":80,"wires":[[]]},{"id":"37170f03.e7cad","type":"inject","z":"5051cb93.cf0d34","name":"","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":90,"y":560,"wires":[["d1b2515d.89157"]]},{"id":"d1b2515d.89157","type":"change","z":"5051cb93.cf0d34","name":"","rules":[{"t":"set","p":"test","pt":"flow","to":"From parent 1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":250,"y":560,"wires":[["ea05925a.2f409"]]},{"id":"ea05925a.2f409","type":"subflow:a11d54.726bd2b","z":"5051cb93.cf0d34","name":"","env":[],"x":380,"y":620,"wires":[["6b0da688.4a4178"]]},{"id":"6b0da688.4a4178","type":"debug","z":"5051cb93.cf0d34","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":530,"y":620,"wires":[]},{"id":"e5896147.211da","type":"change","z":"5051cb93.cf0d34","name":"","rules":[{"t":"set","p":"test","pt":"flow","to":"From parent 2","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":250,"y":700,"wires":[["ea05925a.2f409"]]},{"id":"8d4e3fd3.745dc","type":"inject","z":"5051cb93.cf0d34","name":"","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":90,"y":700,"wires":[["e5896147.211da"]]}]

```

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [20 October 2019 09:36 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/18 "2019-10-20T09:36:59Z")

</div>

Thanks @knolleary and @dceejay.

With that resolved, how would I do what was shown in this real line:  
`var debug = flow.get(device+'_Button_Debug') || false;`

`device` is resolved earlier from a local `context.get( )`.

My resolution to it is:  
`var debug = flow.get("$parent.device"+'_Button_Debug' ) || false;`

correct?

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [20 October 2019 09:37 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/19 "2019-10-20T09:37:19Z")

</div>

I notice that how to use flow context in a subflow is documented in  
[https://nodered.org/docs/user-guide/context](https://nodered.org/docs/user-guide/context)  
but not in  
[https://nodered.org/docs/user-guide/editor/workspace/subflows](https://nodered.org/docs/user-guide/editor/workspace/subflows)

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [20 October 2019 09:43 UTC](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910/20 "2019-10-20T09:43:09Z")

</div>

> [@Trying\_to\_learn](#):
>
> var debug = flow.get("$parent.device"+'\_Button\_Debug' ) || false;

I think

```auto
var debug = flow.get(`$parent.${device}_Button_Debug`) || false;

```

or

```auto
var debug = flow.get("$parent." + device + "_Button_Debug") || false;

```

if you are a Luddite.

[Next page](https://discourse.nodered.org/t/sub-flows-i-am-missing-something-in-how-they-work/16910.md?page=2)
