2

I have started to play round with Node.js but I am having trouble with asynchronous functions I was able to make a game small game. But the only way I was able to get the asynchronous functions to work with the synchronous functions was to use global variables.

Example

var promptly = require("./promptly"); //needed for input {npm install promptly}
var firstName;
var lastName;

GetFirstName();

function GetFirstName() { //asynchronous function
    promptly.prompt('You first name: ', function (err,value) {
        firstName = value;
        getLastName();
    });
}

function getLastName() { //asynchronous function
    promptly.prompt('You last name: ', function (err,value) {
        lastName = value;
        printName();
    });
}

function printName() { //synchronous function
    console.log(firstName+" "+lastName);
}

This works but my small game with 5 asynchronous function ended with 14 global variable. so my question is what is the right way of doing something like this?

6
  • 3
    There should be zero global variables. Do you know about passing arguments to functions? That's how you pass information from one context to another function without using globals. This is a very basic programming concept so it may be really helpful for you to follow some online tutorial on programming basics rather than just trying to write code without appropriate training. Commented Aug 18, 2016 at 1:09
  • 1
    Educate yourself on promises, that's the proper way to use asynchronous functions like they were synchronous. Check f.i. this link about the point of promises: gist.github.com/domenic/3889970. To mess calling asynchronous functions inside of callbacks of asynchronous functions lead to callback hells and its not a solid way to make generic, testable and reusable code. EDIT: actually the @Brandon answer gets to the point Commented Aug 18, 2016 at 1:31
  • I understand that there should be zero global variables I know about passing arguments to functions. The problem is I have lots of functions that get a variable that need to go to a function five function down the line, there must be a better way instead of passing this variable to 4 function that will never use it. Commented Aug 18, 2016 at 1:41
  • @Ashlin they don't call it callback hell because it's an efficient and rational way to write code :) Commented Aug 18, 2016 at 1:53
  • You can also pass lots of things easily by creating a single object that you pass along and then you can have as many properties as you want on that object. This makes it easy to pass things along to far away steps of the process because all the intermediaries just pass along the object and don't have to be aware of the particulars of the other properties on the object other than the ones they want to do something with. You can also easily pass data from one step to the next that way. Commented Aug 18, 2016 at 23:43

2 Answers 2

2

What @jfriend00 is referring to in his/her comment is that when you define a function, you can define parameters that the function should take.

With that in mind, you could rewrite your code to something like this:

var promptly = require("./promptly"); //needed for input {npm install promptly}


GetFirstName();

function GetFirstName() { //asynchronous function
    promptly.prompt('You first name: ', function (err,firstName) {

        getLastName(firstName);
    });
}

function getLastName(firstName) { //asynchronous function
    promptly.prompt('You last name: ', function (err,lastName) {

        printName(firstName, lastName);
    });
}

function printName(firstName, lastName) { //synchronous function
    console.log(firstName+" "+lastName);
}

Note that each 'step' of the process accepts the result from the previous 'step'.

The async technique you're using is affectionately known as callback hell, as the callbacks (i.e., the functions you're passing to .prompt() as the second argument) tend to nest deeply & quickly become unmanageable.

Javascript these days has a lot of solutions to manage this problem. Once you understand the 'flow' of an async program, I recommend looking into some of the more user-friendly options (take my snippets with a grain of salt, they're just meant to illustrate concepts):

async.js - this library has a lot of great utilities that help you write callbacks in more readable ways:

async.series([
  asyncFunction1(arg, callback) {
    // code
    callback()
  },
  asyncFunction2(arg, callback) {
    // code
    callback()
  },
  asyncFunction3(arg, callback) {
    // code
    callback()
  }
]

Promises - a new feature in Javascript and one already supported by libraries. Under the hood these are interesting, but in practice they simply allow for cleaner code and error handling:

asyncFunction1(args) {
  // code
  return x
}
.then(asyncFunction2(x) {
  // code
  return y
})
.then(asyncFunction3(y) {
  // code
  return z
})

async/await - one of the latest attempts at solving the async code challenge. Personally I haven't used them yet but the examples are interesting.

async function getName() {
  let firstName =  await getFirstName()
  let lastName = await getLastName()
  console.log("Your name is " + firstName + lastName)
}

The last article I linked is definitely worth a read for a good overview of the async challenge. It's not a simple concept to grok, but once it clicks, it's pretty intuitive.

Sign up to request clarification or add additional context in comments.

1 Comment

FWIW this is NOT callback hell. This is the SOLUTION to callback hell: to define the functions separately instead of nesting.
0

Pass firstName into getLastName() and then pass firstName and lastName into printName(). Here is some example code:

var promptly = require("promptly");
GetFirstName();

function GetFirstName() {
  promptly.prompt('You first name: ', function (err,value) {
    getLastName(value);
  });
}

function getLastName(firstName) {
  promptly.prompt('You last name: ', function (err,value) {
    printName(firstName, value);
  });
}

function printName(firstName, lastName) {
  console.log(firstName + " " + lastName);
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.