Reputation: 2001
I find it very hard to explain or search for this problem, so I'm asking Stack Overflow.
I'm asking user for user-input in the terminal several times and want to make a function out of it. A function that takes a question and a variable, and the input should be added to the variable.
This is my code:
var name = 'hello',
age = '11'
var readline = require('readline');
// var rl = readline.createInterface(process.stdin, process.stdout);
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
var getInput = function(inputVariable, question, cb) {
rl.question(question, function(answer) {
inputVariable = answer;
rl.close();
cb();
});
}
var askForName = function() {
console.log(1,age, name);
getInput(name, "What's your name? ", askForAge);
}
var askForAge = function() {
console.log(2,age, name);
getInput(age, "How old are you? ", printIt);
}
var printIt = function() {
console.log("Hello, " + name);
console.log(".. and " + age + " old.");
}
askForName();
Thanks!
Upvotes: 4
Views: 2601
Reputation: 5267
you can use an Object
instead a primitive value, because objects are passed by reference, meaning the memory address of the original object will be affected.
In the following example, by leveraging that feature in objects, I also used the Function.prototype.call()
method, to set the execution context of the function (that is useful in case the answers
variable is not global.
//outer variable
var answers = {
name: "hello",
age: "11"
};
var readline = require('readline');
// var rl = readline.createInterface(process.stdin, process.stdout);
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
function getInput (propertyName, question, cb) {
var answers = this; //gets the context associated to the current function
rl.question(question, function(answer) {
answers[propertyName] = answer;
rl.close();
cb();
});
}
function askForName () {
console.log(1, answers);
//sets the execution context of getInput
getInput.call(answers, "name", "What's your name? ", askForAge);
}
function askForAge () {
console.log(2, answers);
//sets the execution context of getInput
getInput.call(answers, "age", "How old are you? ", printIt);
}
function printIt () {
console.log("Hello, " + answers.name);
console.log(".. and " + answers.age + " old.");
}
Upvotes: 1
Reputation: 7771
In node.js applications, this is usually solved using either a callback chain or promises.
Using callbacks, you could write your code like this:
var getInput = function(question, cb) {
rl.question(question, function(answer) {
// Don't set the variable, but return value to callback
rl.close();
cb(answer);
});
}
// ask* take a callback which they call with the value
var askForName = function(cb) {
getInput("What's your name? ", cb);
}
var askForAge = function(cb) {
getInput("How old are you? ", cb);
}
// printIt takes the values as parameters
var printIt = function(name, age) {
console.log("Hello, " + name);
console.log(".. and " + age + " old.");
}
// Now ask for name and age and store them as local variables
// inside callbacks
askForName(function(name) {
askForAge(function(age) {
printIt(name, age);
});
});
I added comments to explain the changes. Basically, the values are only being passed between callbacks, never exposed to another scope.
Upvotes: 3
Reputation: 1546
In javascript, only certain things are passed by reference
- they are objects
and arrays
. all other primitive types (strings, integers, etc.) are not.
With that being said, there are a number of ways for you to get what you are after here.. especially since age
and name
are essentially globals
(at least in the current scope of things)
One way is to just have the getInput()
method return
the value you want, and then assign that to your global
var. Another would be to just write setter
methods for each global
you're wanting to change. There are others, but those are the 2 easiest..
anyways, the following would resolve your issue:
var name = 'hello',
age = '11'
var readline = require('readline');
// var rl = readline.createInterface(process.stdin, process.stdout);
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
var getInput = function(inputVariable, question, cb) {
rl.question(question, function(answer) {
if( inputVariable === 'name' ) {
name = answer;
} else if( inputVariable === 'age' ){
age = answer;
}
rl.close();
cb();
});
}
var askForName = function() {
console.log(1,age, name);
getInput('name', "What's your name? ", askForAge);
}
var askForAge = function() {
console.log(2,age, name);
getInput('age', "How old are you? ", printIt);
}
var printIt = function() {
console.log("Hello, " + name);
console.log(".. and " + age + " old.");
}
askForName();
now, there are more elegant ways of doing this. for instance, you could create a map
, you could change the if statements to a switch
, you could have getInput
return a string via the callback
, etc.
Upvotes: 1
Reputation: 8676
When you pass a variable to a function, changing the reference to it will not affect the original variable. You can modify the variable's properties. However, that shouldn't be used as the main method of passing around variables.
A common way of passing a response from an asynchronous process is to use a callback function. You've almost got it:
var getInput = function( question, cb ) {
rl.question(question, function(answer) {
rl.close();
cb(answer);
});
}
var askForName = function( cb ) {
getInput("What's your name? ", cb);
}
var askForAge = function( cb ) {
getInput("How old are you? ", cb);
}
var printIt = function( name, age ) {
console.log("Hello, " + name);
console.log(".. and " + age + " old.");
}
askForName(function(name) {
askForAge(function(age) {
printIt( name, age );
});
});
Upvotes: 1