0

My question is about a smarter solution / alternative to callbacks / promises or global variables.

Situation: I have a program which is event-driven. I know that Function A will calculate a value v that I will need at a later point. A will be called right at the start of the program. Function B may or may not be triggered by an event at a later point.

Question: How can I pass v from A to B without using a callback, since B should not be called by A but rather by some event. How can I avoid using a global Variable (since they are bad)?

User12547645
  • 6,955
  • 3
  • 38
  • 69
  • 1
    If `B` isn't in the scope of `A`, then global variables are generally the only option. They shouldn't be used excessively, but sometimes they're the right thing. – Barmar Aug 28 '17 at 09:35
  • @Barmar Thank you very much for your comment. I was afraid that was the answer to this question. But let`s wait. Maybe there are other suggestions of things we did not consider. – User12547645 Aug 28 '17 at 09:38
  • Is `A` sync or async? Can the caller of `A` simply inject the value into `B` somehow, e.g. when setting up `B` as an event handler? Is there anything shared between the two, e.g. they're both members of the same class? – deceze Aug 28 '17 at 09:41
  • 1
    Note that the variable doesn't have to be fully global, you can combine `A` and `B` into a local scope that they share. Or you can use objects to package variables. – Barmar Aug 28 '17 at 09:41
  • @deceze They are not member of the shared classes and could be at two completely different parts of the application. `A` may or may not be async. Could be pls explain, why that is important? `B` will always be called after `A`, no matter if `A` is async or not – User12547645 Aug 28 '17 at 14:34

2 Answers2

1

You may use a closure. I mean val is in the scope of Function A, and the event listener can be "registered" from within function A. Since val will be under closure it can still be accessed by the event listener such as;

function A(n) {
  var but = document.getElementById("me"),
      res = document.getElementById("result"),
      val = Math.floor(Math.random() * n) + 1;
  but.addEventListener("click", function(e) {
                                  res.textContent = val;
                                  res.style.backgroundColor = '#' + Math.random().toString(16).substr(-6);
                                });
}

A(100);
<script src="index.js" defer></script>
<label for="me">To get the ready value please click</label>
<button id="me">me..!</button>
<p id="result"></p>

As you see the value is calculated synchronously only once at the beginning but the background color is being calculated every time.

Redu
  • 25,060
  • 6
  • 56
  • 76
0

The best alternative is to have a closed scope with a variable that the two functions can share:

var B, A;
(function() {
  //Local scope variable that is only accessible in this scope
  var v = 1;
  //Define function B
  B = function B() {
    console.log("v is", v);
  };
  //Define function A
  A = function A() {
    setTimeout(function() {
      v++;
      console.log("A has changed the value of v");
    }, 1000);
  };
})();
A(); // --> Start A, which modifies the local variable v
B(); // --> Start B before A has finished. B logs current value of local variable v
setTimeout(function() {
  B(); // --> Start B after A has finished. B logs current value of local variable v
}, 2000);
Emil S. Jørgensen
  • 6,216
  • 1
  • 15
  • 28
  • Thank you very much for your answer, Emil. Good idea, but only works if `A` and `B` are in the same file. They might be at 2 completely different parts of the program, though. Btw: You can do this without using a self calling function, [if you are using `let`](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Statements/let), since this is not using function scope. – User12547645 Aug 28 '17 at 14:47