Crazy idea to use link calls from Blockly nodes

Just writing this down in case I forget

just had an idea for doing a link call from within the node

OK - lets see where this goes

Ignore Blocky for the moment -assume I'm writing a function node

Can I (in anyway, shape or form) make a call to a link node and have it return to my function?
i.e. use an external link flow as as a subroutine?

Yes!

But it's a secret, and could be seen as corporate espionage (unless I have it wrong? - extremely possible)

Without trying to get my head around all that just yet - will it let me call link node and then return back to next line within the function node?

You have a sick mind @cymplecy! :smile:

I don't actually know from the top of my head

I can't imagine wanting to do it but if the function has two outputs:

[{"id":"37c2582930360eff","type":"inject","z":"c6109153bf0ba2c5","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":300,"wires":[["2017b08aff5ed4de"]]},{"id":"2017b08aff5ed4de","type":"function","z":"c6109153bf0ba2c5","name":"function 55","func":"if (! msg.linkrun) {\n    node.warn (\"not run\")\n    return [msg, null]\n}\nnode.warn (\"run\")\nreturn [null, msg];","outputs":2,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":300,"wires":[["16f27a37bf0a943a"],["f81cc22ee0a7fdd4"]]},{"id":"16f27a37bf0a943a","type":"link call","z":"c6109153bf0ba2c5","name":"","links":["ff11e7e37bdf11ce"],"linkType":"static","timeout":"30","x":340,"y":240,"wires":[["2017b08aff5ed4de"]]},{"id":"37b630440f2568a0","type":"change","z":"c6109153bf0ba2c5","name":"","rules":[{"t":"set","p":"linkrun","pt":"msg","to":"hello","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":180,"wires":[["862cdb6b9ca823e7"]]},{"id":"ff11e7e37bdf11ce","type":"link in","z":"c6109153bf0ba2c5","name":"link in 3","links":[],"x":170,"y":180,"wires":[["37b630440f2568a0"]],"l":true},{"id":"862cdb6b9ca823e7","type":"link out","z":"c6109153bf0ba2c5","name":"return","mode":"return","links":[],"x":490,"y":180,"wires":[],"l":true},{"id":"f81cc22ee0a7fdd4","type":"debug","z":"c6109153bf0ba2c5","name":"debug 431","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":590,"y":300,"wires":[]}]
1 Like

Yes - its easy to that :slight_smile:

I'm after the trick to return it back to the point it left in the code within the function node

A more "Node-RED'y" approach for sure.

Looking at the code for the link-call node, I don't see how you could squeeze something into a function node that would replicate it. Also, it creates a hidden connection which might well be very confusing.

I guess the real question is - what are you wanting to achieve with this?

function linkrun () {
    if (! msg.linkrun) {
    node.warn ("not run")
    return [msg, null]
    }
}
linkrun()
node.warn ("Am I not the next line?")
return [null, msg];

But, of course, the "returned" message creates a NEW instance of the function node, it is not the same instance. So if you need to follow on using anything previously calculated, you would have to temporarily save that status and recover it. So you would also need a unique reference to pass across.

Different instance of the function maybe but it's the same message, so any message properties are safe?

1 Like

Reason is to re-use the same link call flow.

So instead of copying/pasting the same code inside several function nodes - it could just call an external flow to do some work and return a value

Unfortuantely, in Blockly, we can't copy/paste blocks into it so it means constructing the same procedure over and over

Another idea has come to me - could I send a msg object out of 2nd node and just have the link flow alter flow context variables?

Could I sit and wait inside the function node for a semaphore flow context value to become true????

So you want re-usable blockly nodes? Effectively creating blockly functions that can be called from other blockly nodes?

Spot On :slight_smile:

Then I think the "right" approach might be a new custom node. One where you create some blockly code with perhaps optional parameters and return value and a name.

Behind the scenes, the JavaScript created by the node is recorded as a function and supplied in a catalogue variable that is accessible to the main blockly nodes.

With care, it should certainly be possible to create JS functions that are shared between the custom nodes in a single module. I do something similar in uibuilder where I have a series of libraries that each create a singleton class. Doing a require on the library module from different node runtimes will always get the same class instance due to the way that require's are cached. Doesn't need to be a singleton class instance though, could be a standard JS object. Since you can retrospectively add to an objects prototype, dynamically adding new functions should be feasible.

It would probably also be possible to do this via an API but that would be less efficient.

#ROTFLOL

I thought you knew my level of coding ability! :slight_smile:

So why can't I

msg = whatever;
flow.context ("semaphore)" = false
node.send(2) // to send msg off to link flow vai 2nd output with a return at the end of the linked flow
Some JS to wait for flow.context("Semaphore") to become true

?

Because that doesn't work. :slight_smile:

You can't "wait" really.

But you could use a link call I suppose. With a link-call, you connect to a link-in, do some stuff and the link-out returns to the link-call who's output you would then send back into your function. But each return is a new entry to your function. So everything will have to be cached in a flow var as you go along.

1 Like

Luckily, I don't need this anymore :slight_smile:

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.