1

I have developed an Electron app with cytoscape.js for graph analysis. Currently, I am in the process of refactoring the code base and moving functions to external modules. Currently I am battling with the variable scope.

  1. I have a number of variables that change when a user interacts with a graph.
  2. I load different UIs (buttons) depending on the type of analysis.

Issue: I cannot pass the recent value of a variable to a module in a way that will simplify the code.

The following code shows the core issue.

// app.js

// require the module
const printValue = require('./printValue.js')

// global variable that I want to access
let selectedNode = ''

// called when a user clicks on node on the graph
cytoscape.on('tap', 'node', selection => {
  // stores the node's data
  selectedNode = selection.target[0]

  // I wan't to avoid that, since I load different configurations
  printValue(selectedNode) // prints the most recent value
})


// loads the different buttons
if (configuration === '1') {
  // I want to transfer it to an external module
  const button = document.getElementById('button-id')
  button.addEventListener('click', () => {
   console.log(selectedNode) // prints the most recent value
  })

  // I want to make this part work
  printValue(selectedNode) // prints '', the initial value of the variable
} else if (configuration === '2') {
  // loads different buttons with different functions
}

The module has the following code

  // module.js

  module.exports = function printValue (value) {
    const button = document.getElementById('button-id')
    button.addEventListener('click', () => {
      console.log(value)
    })
  }

What I want to do, is to move the button declarations and related functions of each configuration in modules. Then call those modules based on the app configuration the user has selected.

or3stis
  • 273
  • 1
  • 3
  • 10
  • 1
    `selectedNode` seems to be a primitive type (string), so when you pass it to your module, it will use the value it had at the moment. You could change `let selectedNode = {}`, then change the value via `selectedNode.value = selection.target[0]`, pass it via `printValue(selectedNode)` and in your module you just use `selectedNode.value` to get the actual current value. (keywords: pass-by-value and pass-by-reference) You are adding a listener to the button every time you call `printValue`, After a while you will end up with multiple console.logs when clicking that one button. – RoyalBingBong Jul 04 '17 at 14:10

1 Answers1

1

Credit goes to Royalbingbong for his helpful comment and reference to pass-by-value.

This was very helpful link where the topic is explained in detail.

Here is the updated (working) code sample.

selectedNode was declared as a string (primitive type), so it couldn't pass the updated value to the module. selectedNode was changed to an object and the variable value is stored with the output key. The selected value is passed to the printValue function, where we print the value of the output key.

// app.js

// require the module
const printValue = require('./printValue.js')

// global variable that I want to access
let selectedNode = {}

// called when a user clicks on node on the graph
cytoscape.on('tap', 'node', selection => {
  // stores the node's data
  selectedNode.output = selection.target[0] // this is the important bit
})

if (configuration === '1') {
  // now works
  printValue(selectedNode) // prints the updated variable
} else if (configuration === '2') {
  // loads different buttons with different functions
}

The module was changed to

// module.js

module.exports = function printValue (selectedNode) {
  const button = document.getElementById('button-id')
  button.addEventListener('click', () => {
   console.log(selectedNode.output) // the other important bit
  })
}
or3stis
  • 273
  • 1
  • 3
  • 10