- [Instructor] In the last lesson,
we introduced the readline module,
and we saw how we can interact with the terminal
using this module, instead of using process standard input
and process standard output directly.
In this lesson, we're going to try to rebuild
the question interface that we built in the last chapter,
but this time using readline.
So, the first thing I'm going to do is
come over to my files and add a new file,
and I'm going to call this questions.js.
And the idea is, we want to have a variable
that can hold our questions, like an array,
and within this array, we want to be able
to add any number of questions, and have those questions
asked to the user through the terminal.
So, we'll go ahead and ask, "What is your name?",
"Where do you live?",
and "What are you going to do with node js?".
So sometimes when I have a coding challenge,
I try to think about what I do
and represent it as a function call.
So, for instance I know that we need to collect
the answers from the user in the terminal.
I'm not necessarily sure how to do that,
but I can imagine that there would be a function
called collectAnswers.
And, without knowing how the collectAnswers function
will work, what I do know is I want
to send it an array of questions,
and I want the collectAnswers function
to ask every question in the array,
in the order that they're presented, of the user.
And, when I get a list of answers back,
I can handle that with a callback function.
So, I know that the second argument
of my collectAnswers function
should probably be a callback function,
and that callback function should pass
a list of answers back.
So, I send a list of questions in as an array,
and I expect a list of answers back.
So, let's go ahead and see what I might do with this,
so for instance when we get an answer I can
console, log, "Thank you for your answers".
And, I can also console, log, the answers,
so we can take a look at that list,
and I'll also call process.exit.
Alright, so this is what I want to do,
and at this point I might not necessarily be sure
how to do it, but I know that I need a function
called collectAnswers, so I'm going to go ahead
and create that function.
And, the first argument that the collectAnswers function
is going to take, is an array of questions,
so I'll go ahead and call them questions.
And, the second argument is a callback function
to be invoked when we're finished,
so I'm going to call this done,
meaning I want to invoke this function
once the user has answered all of the questions.
So, we'll create the function body,
and what we're going to do is
we're going to have an array of answers,
and that's an empty array to get us started.
But, whenever we're done, we're going to invoke that argument,
the done argument, and pass the answers back.
So, once we've received all of the answers
we can send it back to the callback function.
I'm just going to go ahead and comment this out,
'cause we don't want to do that yet.
The first thing we need to do is ask the question,
and collect the answers.
That's where the readline interface is going to help.
So, I'll come up here and pull in readline,
require readline,
and I'm going to also create our interface,
so const rl equals readline.createInterface,
and we are going to use for input,
process dot standard input,
process.stdin, and for output, process.stdout,
and maybe we should spell process correctly.
Great, so now we have a readline interface
for answering questions.
So, I'm not really sure what I'd want to do next,
I do know I need to ask the first question,
and one thing I can do is grab the first question
by destructuring it from our array of questions.
So, if I wanted to I could get the first question,
second question, or third question
by destructuring it from the array of questions.
So, that's how we're able to get the first item
in the array, the second item in the array,
or the third item in the array.
In this case I only want the first question,
so I'm not going to bother with asking
for the second or third question.
So, that would give me, "What is your name?".
And the next thing I know I need to do
is I need the ability to ask that question.
So, I'm going to go ahead and say readline dot question,
firstQuestion.
And, remember readline, the first argument is the string,
and the second argument is a function
that will be invoked once the question is answered.
So, I'm just going to call this questionAnswered.
So, here I'm going to get rid of our little call
to done, answers, on line 18,
and I'm going to create this questionAnswered function.
So, this is the function that readline will invoke
once the user has answered the question,
so we know this function is going to take in the answer.
And, what I'm going to go ahead and do with that
is push the answer into the answers array,
so when the user answers a question,
we're going to push that answer
directly into our array of answers.
And then, the next thing we're going to do
is check to see if the user has answered all the questions.
We can find that out by typing,
if, answers.length is still
less than questions.length,
then what we want to do is ask another question.
So, that means if the length of the answers array
doesn't match the length of the questions array,
we probably need to ask another question.
So, I can say rl.question again,
and this time we'll find the question
from the questions array directly,
and in order to know which one,
we can use the answers.length.
So, if I have one answer within my answers array,
then I'm going to ask questions one,
which would give me the second question
within the questions array.
Once I have two answers, the answers array
will be of length two, so I'll ask questions two
which will give me the third question.
Now, if answers.length is not less than questions.length,
that means we have the same number of answers
as we do questions, which means that we're finished.
So, I'm going to go ahead and add else,
so we can go ahead and invoke done,
and we can pass all of the answers
back to the callback function.
All right great, let's go ahead and give it a shot.
So, I'll come over here to the terminal
and we will node questions.js.
It says "What is your name?", Alex,
"Where do you live?", Tahoe City,
"What are you going to do with node js?", change the world.
And, we can see the message thank you for your answers,
and then, here are my answers,
the answer to the first question was "Alex",
the answer to the second question was "Tahoe City",
and the answer to the third question was "Change the world".
So, let's just do a quick recap.
We created a collect answers function
that we can just simply send an array of questions,
and a callback to handle once we have all of the answers.
And, in this case we're just saying
"Thank you for your answers.",
and logging the answers array right before we exit.
The function itself takes in the questions
as the first argument, that's our array of questions,
as well as a callback to invoke once we're done.
And then, we create a new array of answers,
on line 27 we use readline to ask the first question,
and every other question is asked on line 21.
And, once we have the question answered,
our questionAnswered function will be invoked,
and we will add our answer to the answers array.
If we don't have all of your answers,
we're going to ask another question again,
but when we do have all of our answers
we're going to invoke the done callback
and pass the answers there.