Question

I have been learning nodejs, and one thing that continues to boggle my mind is async programming that nodejs is built on. Maybe I am doing something wrong, but despite all my research I can't wrap my mind around how I should adapt to it coming from synchronous programming background. I would really appreciate if someone gave me a simple async example based on the below structure, given you want to call func2 from anywhere.

function1(){
  var obj = function2();
  console.log(obj); //"undefined".
}

function2(){
  //do stuff with DB and get obj
  console.log(obj); //logs obj.
  return obj;
}

The problem I stumbled upon is that obj prints as undefined in func1, while func2 has no problems with it. When I nested the functions within each other it worked, leading me to believe that due to async nature of nodejs it proceeded to log in func1 before func2 was finished. Am I wrong with my assumptions?

What I struggle with in the above example, is how would I code the functions instead of nesting them within each other, so I can call func2 from several different functions at once. I've looked into callbacks but couldn't understand the examples given in various answers with a function inside a function.

Was it helpful?

Solution

You have to define functions (i.e. the callbacks) within functions.

1  function function1(){
2    function2(function(obj) {
3      console.log(obj); //logs obj.
     });
   }

4  function function2(callbackFn){
     //do stuff with DB and get obj
     console.log(obj); //logs obj.
5    callbackFn(obj);
   }

function2 can be called from many places at once, not just function1.

If you can be more specific about what you don't understand, then you might get a better answer.


Functions are values, just like numbers, strings and objects.

This is the core fundamental of functional programming, and probably the thing you haven't grasped. In JavaScript, as in a number of languages, functions are not special*. This is different to languages like C or Java, where functions/methods are different to the usual values you deal with in your code.

2; // Here is a number
var a = 2; // I can assign it to a variable
console.log(2); // I can pass it as a function argument

function() {} // Here is a function
var a = function() {}; // I can assign it to a variable
console.log(function() {}); // I can pass it as a function argument

function jim() {} // This function's name is jim
var a = jim; // I can assign it to a variable
console.log(jim); // I can pass it as a function argument

(function() {})(); // I can call a function without giving it any names
jim(); // I can call a named function
a(); // I can call a function via a variable
jim.call(this, arg1); // Or I can get complicated

So, we can declare functions and pass them around, separately to calling them. Now, what about the code we started with.

  1. Declare a new function called function1 that takes no arguments
  2. When function1 is called, call function2 with a single argument, a new nameless function that takes an obj argument
  3. When the anonymous function is called, call console.log with the value passed for obj
  4. Declare a new function called function2 that takes a single argument callbackFn
  5. Call the value passed for callbackFn with a single argument, the obj we got from somewhere

So the declaration order is 1, 4, 2; and the execution order is 2, 5, 3.

*OK, they're a little special. Their definitions are hoisted, you can execute the code they represent, and their declarations create scope and closures. But those are all questions for another time.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top