How can I display a Javascript output in real time? - javascript

Apologies if this is a simple question, but is there a way to output Javascript to the console in real-time, while pausing at each user interaction. In other words, if I did something as simple as...
console.log("What's your name: ");
let userName = prompt("What is your name?");
console.log(userName);
console.log("\n");
console.log("Nice to meet you " + userName + "! What is your age?");
let userAge = prompt("What is your age?");
console.log(userAge);
...can I get the name outputted to the screen before the age prompt comes up? This is doable in other teaching environments (MS Basic & the command prompt), but either doesn't exist in Javascript, or I'm missing something.
Thanks for helping the newb!

You can make use of setTimeout, something like this:
console.log("What's your name: ");
let userName = prompt("What is your name?");
console.log(userName);
console.log("\n");
setTimeout(function(){
console.log("Nice to meet you " + userName + "! What is your age?");
let userAge = prompt("What is your age?");
console.log(userAge);
},1000)
Note: This is one way to do it there are ample of other ways to do it.
In case if you want to use promises:
let userName,userAge, userSport;
function basic(){
console.log("What's your name: ");
var promise1 = new Promise(function(resolve, reject){
userName = prompt("What is your name?");
resolve(userName)
})
promise1.then(function(value){
console.log(value);
console.log("\n");
console.log("Nice to meet you " + value + "! What is your age?");
var promise2 = new Promise(function(resolve, reject){
userAge = prompt("What is your age?");
resolve(userAge)
})
promise2.then(function(value){
console.log(value)
console.log("Nice to meet you " + userName + " aged: " +userAge + ". Let us know your favorite sports")
var promise3 = new Promise(function(resolve, reject){
userSport = prompt("What is your favorite sports?");
resolve(userSport)
})
promise3.then(function(value){
console.log(value)
console.log("Nice to meet you " + userName + " aged: " +userAge + " and your favorite sports is " +value)
console.log("\n");
console.log("Thanks");
})
})
})
}
basic()

You can use the async/await functionality and promises. I personally do not always like to use .then so this is my version of using Promises.
const Q1 = () => new Promise(resolve => {
let userName = prompt('What is your name?');
console.log(`What is your name: ${userName}`);
resolve(userName);
})
const Q2 = (userName) => new Promise(resolve => {
console.log(`Nice to meet you ${userName}! What is your age?`);
let age = prompt('What is your age?');
console.log(age);
resolve(age);
})
const userPrompt = async () => {
let name = await Q1();
let age = await Q2(name); // assigned to variable should you want to use it in next question
}
userPrompt();
You can now just add additional questions as functions.
Also here is a link to a JSFiddle. If you run it and open the console you will see that the name is displayed before the age prompt is opened.

Related

Can't get value of array

Still can't understand my mistake with this code.
All what I want it - via prompt get all list of users (name / surname)
function UserList() {
let users = [];
while (true) {
let response = prompt('Please, enter your name surname?');
if (response == null) {
alert('cancel');
break;
}
users.push(response.split(' '));
}
return users;
}
function User() {
this.name = userList[0];
this.surname = userList[1];
this.regDate = new Date;
for (i = 0; i < userList.length; ++i) {
console.log('Name: ' + this.name + ' Surname: ' + this.surname + '. Date of registration : ' + this.regDate)
}
}
let userList = new UserList();
let user = new User();
And I faced with a misunderstanding why I cant get first word of prompt despite I put users.push (response.split(' ')).
userList [0] - shows first index of array instead first word.
And second I want to get all list of users in console.log but instead it I get the same string depending on length of array
userList[0] in the function User will return an array: ['name', 'surname'].
To get the first name for example, you need to use this.name = userList[i][0]
function UserList() {
let users = [];
while (true) {
let response = prompt('Please, enter your name surname?');
if (response == null) {
alert('cancel');
break;
}
users.push(response.split(' '));
}
return users;
}
function User() {
for (var i = 0; i < userList.length; ++i) {
this.name = userList[i][0];
this.surname = userList[i][1];
this.regDate = new Date;
console.log('Name: ' + this.name + ' Surname: ' + this.surname + '. Date of registration : ' + this.regDate)
}
}
let userList = new UserList();
let user = new User();
You are pushing an array in an other array, so your index is not correct (array looks like this: [["firstname", "lastname"]]). You could spread the items when pushing using the spread operator (...), you could also flatten the array using flat().
Also when creating a date, use new Date().
function UserList() {
let users = [];
while (true) {
let response = prompt('Please, enter your name surname?');
if (response == null) {
alert('cancel');
break;
}
users.push(...response.split(' ')); // flatten
}
return users;
}
function User() {
this.name = userList[0];
this.surname = userList[1];
this.regDate = new Date(); // ()
console.log('Name: ' + this.name + ' Surname: ' +
this.surname + '. Date of registration : ' + this.regDate)
}
let userList = new UserList();
let user = new User();
Using flat()
return users.flat();
Edit
I actually understood the question wrong (thought you only wanted 1 user), the other answer should be correct and makes more sense.
UserList shouldn't be a constructor. It should just be a function that returns an array of names.
You shouldn't be iterating over the list of users within User. You should then be iterating over the array creating one new User on each iteration which should be generated from a constructor. You can just pass in each name from the array and build an new object.
function getNames() {
const users = [];
while (true) {
const response = prompt('Please, enter your first and last names');
if (response == null) break;
users.push(response.split(' '));
}
return users;
}
// Pass in a user name from the array as an argument
// It's array so we can destructure the first and last name
// immediately
function User([first, last]) {
this.first = first;
this.last = last;
this.regDate = new Date();
this.message = `Name: ${this.first}. Surname: ${this.last}. Date of registration: ${this.regDate}.`;
}
// Iterate over the array generated by `getUsers`
// and for each name create a new user.
for (let name of getNames()) {
console.log(new User(name));
}
Additional documentation
Destructuring assignment

Node.js - Promise callbacks override custom objects

This is my first post to this site, so I apologize in advance of any lack of data or tags, etc. I've been using this site for years, and it always helped me, but now I'm truly lost, and I couldn't find an answer anywhere.
I have an application where I need to call a web service 10 times, each time with a different parameter. The return payload is complex, so I created a custom object to hold the data. I need data from all 10 calls before moving forward with my code, which led me to callback hell. I'm trying to use Promises to simplify this, but this is where I'm facing this weird issue. I'm able to replicate this issue with a simple class:
Custom Object (Person):
var person = {
firstName : String,
lastName : String,
age : Number
}
function Person() { //getters and setters
} module.exports = Person;
Function getToken (returns a specific token my web service calls need), here replaced with a simple string:
function getToken() {
return new Promise(function(resolve, reject) {
var x = "random token";
console.log('getting token');
setTimeout(function(){resolve(x)}, 200);
});
}
Function getAction: in my real app, it calls the web service. Here it just creates a random person with an ID as input:
function getAction(uuid) {
return new Promise(resolve => {
var newPerson = new Person();
newPerson.setFirstName("John " + uuid);
newPerson.setLastName("Doe");
newPerson.setAge(20);
console.log("---> Returning Person " + newPerson.getFirstName());
setTimeout(function(){resolve(newPerson)}, 300);
});
}
Function getActions: calls getAction for each input parameter. This function itself must return a Promise because there's another function waiting for all the data to be available before continuing.
function getActions() {
return new Promise(function(resolve, reject) {
getToken().then(async function(tokenret) {
var userIds = ["001", "002", "003", "004", "005", "006", "007", "008", "009", "010" ];
var myPromise = Promise.join;
myPromise(getAction(userIds[0]), getAction(userIds[1]), getAction(userIds[2]), function(personOne, personTwo, personThree) {
console.log("Person One: " + personOne.getFirstName());
console.log("Person Two: " + personTwo.getFirstName());
console.log("Person Three: " + personThree.getFirstName());
});
}).catch(function(rej) {console.log("Promise Failed! " + rej);});
});
}
The output for this execution is:
---> Returning Person John 001
---> Returning Person John 002
---> Returning Person John 003
Person One: John 003
Person Two: John 003
Person Three: John 003
We can see that the getAction function was executed in the right order, with the right parameters. But all 3 variables created in the getActions function have the value from the last execution.
I also tried this code:
const allPromises = userIds.map(userIds => getAction(userIds));
await Promise.all(allPromises).then(function(allResults) {
console.log("Received " + allResults.length + " records");
var thisPersonZero = allResults[0];
console.log("This person 0: " + thisPersonZero.getFirstName());
var thisPersonOne = allResults[1];
console.log("This person 1 " + + thisPersonOne.getFirstName());
var thisPersonTwo = allResults[2];
console.log("This person 2 " + + thisPersonTwo.getFirstName());
console.log("Recapping");
console.log("This person 0: " + thisPersonZero.getFirstName());
console.log("This person 1: " + thisPersonOne.getFirstName());
console.log("This person 2: " + thisPersonTwo.getFirstName());
});
And I got this output:
---> Returning Person John 001
---> Returning Person John 002
---> Returning Person John 003
---> Returning Person John 004
---> Returning Person John 005
---> Returning Person John 006
---> Returning Person John 007
---> Returning Person John 008
---> Returning Person John 009
---> Returning Person John 010
Received 10 records
This person 0: John 010
This person 1 John 010
This person 2 John 010
Recapping
This person 0: John 010
This person 1: John 010
This person 2: John 010
Finally, I tried using await, which generated even weirder results:
var firstPerson = await getAction(userIds[0]);
console.log("First Person: " + firstPerson.getFirstName());
var secondPerson = await getAction(userIds[1]);
console.log("Second Person: " + secondPerson.getFirstName());
console.log("Recapping");
console.log("First Person: " + firstPerson.getFirstName());
console.log("Second Person: " + secondPerson.getFirstName());
Result:
---> Returning Person John 001
First Person: John 001
---> Returning Person John 002
Second Person: John 002
Recapping
First Person: John 002
Second Person: John 002
So the value is correct, until the callback for the next Promise, which replaces the value for all the variables. The behavior is the same if I create copies of the variable, even using JSON.parse(JSON.stringify()).
This code works perfectly if I use strings instead of the Person object. However it would be extremely cumbersome to try and do this without custom objects.
I'm sure that I am making some very basic mistake, but even though this seems to be very straightforward, I couldn't find anything on this particular issue anywhere. This issue is happening with Node versions 9.5 and 10, running on MacOS (if it makes any difference).
Any help will be very much appreciated. Thanks in advance!
Full code snippet:
// Person.js
var person = {
firstName : String,
lastName : String,
age : Number
}
function Person() {
Person.prototype.setFirstName = function(firstName) { person.firstName = firstName; }
Person.prototype.setLastName = function(lastName) { person.lastName = lastName; }
Person.prototype.setAge = function(age) { person.age = age; }
Person.prototype.getFirstName = function() { return (typeof person.firstName === 'undefined') ? '' : person.firstName; }
Person.prototype.getLastName = function() { return (typeof person.lastName === 'undefined') ? '' : person.lastName; }
Person.prototype.getAge = function() { return (typeof person.age === 'undefined') ? 0 : person.age; }
}
module.exports = Person;
// Error.js
var Promise = require('bluebird');
var Person = require("./models/Person");
function getToken() {
return new Promise(function(resolve, reject) {
var x = "random token";
console.log('getting token');
setTimeout(function(){resolve(x)}, 200);
});
}
function getActions() {
return new Promise(function(resolve, reject) {
getToken().then(async function(tokenret) {
var userIds = ["001", "002", "003", "004", "005", "006", "007", "008", "009", "010" ];
/*
var myPromise = Promise.join;
myPromise(getAction(userIds[0]), getAction(userIds[1]), getAction(userIds[2]), function(personOne, personTwo, personThree) {
console.log("Person One: " + personOne.getFirstName());
console.log("Person Two: " + personTwo.getFirstName());
console.log("Person Three: " + personThree.getFirstName());
});
*/
var firstPerson = await getAction(userIds[0]);
console.log("First Person: " + firstPerson.getFirstName());
var secondPerson = await getAction(userIds[1]);
console.log("Second Person: " + secondPerson.getFirstName());
console.log("Recapping");
console.log("First Person: " + firstPerson.getFirstName());
console.log("Second Person: " + secondPerson.getFirstName());
/*
const allPromises = userIds.map(userIds => getAction(userIds));
await Promise.all(allPromises).then(function(allResults) {
for (var x = 0; x < allResults.length; x++)
{
var thisPerson = allResults[x];
console.log("This Person: " + thisPerson.getFirstName());
}
console.log("Received " + allResults.length + " records");
var thisPersonZero = allResults[0];
console.log("This person 0: " + thisPersonZero.getFirstName());
var thisPersonOne = allResults[1];
console.log("This person 1 " + thisPersonOne.getFirstName());
var thisPersonTwo = allResults[2];
console.log("This person 2 " + thisPersonTwo.getFirstName());
console.log("Recapping");
console.log("This person 0: " + thisPersonZero.getFirstName());
console.log("This person 1: " + thisPersonOne.getFirstName());
console.log("This person 2: " + thisPersonTwo.getFirstName());
});
*/
}).catch(function(rej) {console.log("Promise Failed! " + rej);});
});
}
function getAction(uuid) {
return new Promise(resolve => {
var newPerson = new Person();
newPerson.setFirstName("John " + uuid);
newPerson.setLastName("Doe");
newPerson.setAge(20);
console.log("---> Returning Person " + newPerson.getFirstName());
setTimeout(function(){resolve(newPerson)}, 300);
});
}
getActions();
Without going too much into your code, I can already tell you that your Person 'class' methods are using person object declared at the top of the Person.js file. Fix those to use this and that should be it.
Person.prototype.setFirstName = function(firstName) { this.firstName = firstName; }
The way you have it set now the methods keep mutating the same object.

Pull number value from string

So I need to pull a number value from a string. I currently have a working solution but I feel that maybe I can improve this using a regular expression or something.
Here is my working solution
var subject = "This is a test message [REF: 2323232]";
if(subject.indexOf("[REF: ") > -1){
var startIndex = subject.indexOf("[REF: ");
var result = subject.substring(startIndex);
var indexOfLastBrace = result.indexOf("]");
var IndexOfRef = result.indexOf("[REF: ");
var ticketNumber = result.substring(IndexOfRef + 6, indexOfLastBrace);
if(!isNaN(ticketNumber)){
console.log("The ticket number is " + ticketNumber)
console.log("Valid ticket number");
}
else{
console.log("Invalid ticket number");
}
}
As you can see I'm trying to pull the number value from after the "[REF: " string.
// Change of the text for better test results
var subject = "hjavsdghvwh jgya 16162vjgahg451514vjgejd5555v fhgv f 262641hvgf 665115bs cj15551whfhwj511";
var regex = /\d+/g;
let number = subject.match( regex )
console.log(number)
It Will return array for now, and if no match found, it will return null.
For most of the time, when i used this regex i get perfect result unless if string contains decimal values.
var str = 'This is a test message [REF: 2323232]'
var res = str.match(/\[REF:\s?(\d+)\]/, str)
console.log(res[1])
If you don't want to use a regular expression (I tend to stay away from them, even though I know they are powerful), here is another way to do it:
// Your code:
/*var subject = "This is a test message [REF: 2323232]";
if(subject.indexOf("[REF: ") > -1){
var startIndex = subject.indexOf("[REF: ");
var result = subject.substring(startIndex);
var indexOfLastBrace = result.indexOf("]");
var IndexOfRef = result.indexOf("[REF: ");
var ticketNumber = result.substring(IndexOfRef + 6, indexOfLastBrace);
if(!isNaN(ticketNumber)){
console.log("The ticket number is " + ticketNumber)
console.log("Valid ticket number");
}
else{
console.log("Invalid ticket number");
}
}*/
// New code:
const subject = "This is a test message [REF: 2323232]";
const codeAsString = subject.split('[REF: ')[1]
.split(']')
.join('');
if (!isNaN(parseInt(codeAsString))) {
console.log('Valid ticket number: ', parseInt(codeAsString));
}
else {
console.log('Invalid ticket number: ', codeAsString);
}
This will extract number
var subject = "This is a test message [REF: 2323232]";
var onlyNum = subject.replace(/.*(:\s)(\d*)\]$/,'$2');
console.log(onlyNum)
Here, same but the number is now a real int
var subject = "This is a test message [REF: 2323232]";
var onlyNum = parseInt(subject.replace(/.*(:\s)(\d*)\]$/,'$2'));
console.log(onlyNum)

Array issues (javascript)

I created a small function that stores the book isbn, it's name and it's author. Everything is fine until I start to print out array. On every entery that completes the object into array, I want it to be printed one after another in new row, but this one is printing the objects from beginning every time when a new object is inserted. How do I fix this?
var books = [];
function blaBla(){
while(isbn != null || name != null || writer != null){
var isbn = window.prompt("Enter ISBN");
var name = window.prompt("Enter name of the book");
var writer = window.prompt("Enter name of the writer");
var patternString = /^[a-zA-Z]+$/;
var patternNum = /^[0-9]+$/;
if(isbn.match(patternNum)){
if(name.match(patternString)){
if(writer.match(patternString)){
books.push({
isbn: isbn,
name: name,
writer: writer
});
}
}
}
for (var i=0; i<books.length; i++){
document.write(books[i].isbn + " - " + books[i].name + " - " + books[i].writer + "</br>");
}
}
}
PS: How do I make it even more "cleaner", so when I hit cancel on prompt, it automatically stops with entering data into array, while, if i stop it on the "writer" prompt, it deletes previous entries for that object (last isbn and last name of the book)?
Thanks in advance.
You might want to give a little more context as to what this function is doing so we can help make your code cleaner as requested. I've separated the collection logic from the display logic here, and also used a while (true) loop with breaks on null or invalid inputs which will stop the collection of data.
Please note that prompt/alert boxes are a hideous way of collecting user input though (very awkward user experience). Consider using a table, input fields, and some jQuery instead to add rows and validate what the user has entered into input boxes.
var books = [];
function collectResponses() {
var patternString = /^[a-zA-Z]+$/;
var patternNum = /^[0-9]+$/;
while (true) {
var isbn = window.prompt("Enter ISBN");
if (!isbn || !isbn.match(patternNum)) {
break;
}
var name = window.prompt("Enter name of the book");
if (!name || !name.match(patternNum)) {
break;
}
var writer = window.prompt("Enter name of the writer");
if (!writer || !writer.match(patternNum)) {
break;
}
books.push({
isbn: isbn,
name: name,
writer: writer
});
}
}
function displayResponses() {
for (var i=0; i<books.length; i++){
document.write(books[i].isbn + " - " + books[i].name + " - " + books[i].writer + "</br>");
}
}

Loading a different file if user says correct response

On lines, 34-41 I'm trying to make it so if the user types in games it will automatically load a game from a different file, and the same for talk. How can I do this with js?
var storeUsersInfo = [];
var amountOfUsers = prompt("How many users do you want?");
amountOfUsers = parseInt(amountOfUsers);
function returnUserInput() {
var askFirstName = prompt("What is your first name?");
var askLastName = prompt("What is your last name" + " " + titleCase(askFirstName) + "?");
while(true) {
var askAge = prompt("How old are you" + " " + titleCase(askFirstName) + " " + titleCase(askLastName) + "?");
if(Number.isInteger(Number.parseInt(askAge))) break;
alert("Not a valid input, please enter your response as a number.");
};
return {
firstName: titleCase(askFirstName),
lastName: titleCase(askLastName),
age: askAge
};
};
function titleCase(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
};
for(var i = 0; i < amountOfUsers; i++) {
storeUsersInfo[i] = returnUserInput();
}
console.log("Your information has been stored in the object below.");
console.log(storeUsersInfo);
var askUserToDoSomethingElse = prompt("Do you want to do something else?"); // Yes or No
if(askUserToDoSomethingElse = "yes") {
var chooseSomethingElse = prompt("If you want to play a game type game, or if you just want to talk type talk.");
if(chooseSomethingElse === "game") {
alert("Okay!");
} else if (chooseSomethingElse === "talk") {
alert("Okay!");
}
};
You have two options :
1.) XMLHttpRequest
var client = new XMLHttpRequest();
client.open('GET', '/<fileName>');
client.onreadystatechange = function() {
//do something with your file
}
2.)Using Jquery
jQuery.get('http://localhost/foo.txt', function(data) {
//file loaded in data. Now you can use it.
});

Categories