Link to home
Start Free TrialLog in
Avatar of Jimbo99999
Jimbo99999Flag for United States of America

asked on

Node Js -- Wait for Function to complete before continuing

Hello There

i am a VB.net programmer by trade.  But now I am  coding some javascript and am having a bit of trouble.  I am calling a function to get data from a mySql database and then formatting for display in the console.  Then under that, I want to put
a User entry prompt.  The problem is the User entry line is displaying first then the data.  

How can I get the mySql data to print to the console first and when done prompt the User for input? It "feels" like the sql statement is finishing after the prompt is displayed. So I need to make sure it finishes first.

Any ideas?

Thanks,
jimbo99999
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Can you show us some code - we can't help you unless we know what the code looks like.
Avatar of Jimbo99999

ASKER

GoDoSomeStuff();
console.log("How")
console.log("are")
console.log("you?")

I am looking to have everything in GoDoSomeStuff() finish before the 3 console logs are executed.
You probably will need to show the code inside GoDoSomeStuff() as there is a high likelihood you are using an ajax (async) call. If so, you either need to arbitrarily wait or use the complete|success function of the ajax call to do your console logs or run a callback function that has your console logs in it.
I will post it when I get home in a bit.  But in summary i am doing a select statement using 2 user inputs. The data is in mysql. I am looping through the result set outputting the 10 records back to the console. But the next user prompt that i want to appear under that data is appearing on the first line of the 10 console logs displacing my column headings to the right.  

I will do a screen print of the output.  
Thank you for the help.
Jimbo99999
That is not enough code. If GoDoSomeStuff() contains async calls then you would need to put your console.log statements in the completion call back of those calls (or use a Promise and Promise.all to wait on multiple async events).

The code is important here.

I will do a screen print of the output.  
That will be useful but the code that generates it is what is actually required.
unction selectAllProducts() {
	cnx.query("Select * from products", function(err,res) {
		if(err) throw err;
		for (var i in res) {
			var product = new Product(res[i].item_id, res[i].product_name, res[i].product_sales, res[i].department_name, res[i].price, res[i].stock_qty);
			products.push(product);
		};
		var columns = columnify(products);
		console.log(columns);
	});
};

Open in new window

Here is the output I am getting:

User generated image

Here is where I am calling the SelectAllPridcuts function from:

function productTransaction () {

	selectAllProducts();
	
	inquirer.prompt([
	    {
	    	name: "item",
	        message: "What is the id of the item you would like to purchase? [Quit with Q]",
	        validate: function( value ) {
	        	if (value >= 0 && value <= 10) {
          			return true;
	        	} else if (value == "Q") {
	        		console.log("yitt")
        			process.exit();
        		} else {
          			return 'Please enter a valid item_id!';
        		}
        	}
	    }, 
	    {
	   		name: "qty",
	    	message: "How many would you like?",
	    	validate: function( value ) {
	        	if (isNaN(value)) {
	        		return 'Please enter a valid item_id!';
	        	} else {
        			return true;
        		}
        	}
	  	}
	]).then(function(answers) {

Open in new window

I am trying to get the "What is the id of the item you would like to purchase?" console log below the 10 rows of output.

Thanks for helping,
jimbo99999
cnx.query("Select * from products", function(err,res) {
		if(err) throw err;
		for (var i in res) {
			var product = new Product(res[i].item_id, res[i].product_name, res[i].product_sales, res[i].department_name, res[i].price, res[i].stock_qty);
			products.push(product);
		};
		var columns = columnify(products);
		console.log(columns);
	});

Open in new window


This is an asynchronous request. What this means is that the query is initiated and control returns immediately to the program while the query continues in the background.

This plays out as follows

1. You call selectAllProducts
2. The function starts the query and returns immediately (you gave query a call back function to call when the query is done)
3. Control returns to where selectAllProducts was call
[AT THIS POINT THE QUERY IS STILL PROCESSING IN THE BACKGROUND]
4. No you output the AFTER QUERY code - it is immediately reflected on the screen - remember query still processing so it has not done its output yet
5. Code completes
[A (RELATIVELY) VERY LONG TIME LATER]
Query completes
Callback function is invoked
Output in callback is processed.

Query output appears after output already shown.

What you need to do is put all the code you want to run when the query has completed in the completion call back function.
In other words ....
cnx.query("Select * from products", function(err,res) {

// PUT YOUR POST QUERY PROCESSING CODE HERE
		if(err) throw err;
		for (var i in res) {
			var product = new Product(res[i].item_id, res[i].product_name, res[i].product_sales, res[i].department_name, res[i].price, res[i].stock_qty);
			products.push(product);
		};
		var columns = columnify(products);
		console.log(columns);
	});

Open in new window

Hello. If you don't mind me asking...I would put all my code for the prompting after the console outputting in selectAllProducts?

So the processing stays on the query line and waits till done before continuing?


Thanks for your patience as I am new to js and node.
ASKER CERTIFIED SOLUTION
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
node app is not like vb.net app
unlike  most .net app, the app doesn't wait user input or for him to close the application
instead it run the code and close
your query is an async call, this block :
cnx.query("Select * from products", function(err,res) {
...
});
// next line of code
but doesn't wait and run the next line of code
your second issue is to prompt the user something, i see you're using inquirer for that purpose, why not

just be sure to call it inside your block
see more about promise and async here,  :
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

if you need to do a comparaison with .net it's a bit like Threads, you run a new thread but your code don't wait this thread to finish it's task

function questions(results) {
	inquirer.prompt([
		{
			name: "item",
			message: "What is the id of the item you would like to purchase? [Quit with Q]",
			validate: function( value ) {
				if (value >= 0 && value <= 10) {
		  			return true;
				} else if (value == "Q") {
					console.log("yitt")
					process.exit();
				} else {
		  			return 'Please enter a valid item_id!';
				}
			}
		}, 
		{
	   		name: "qty",
			message: "How many would you like?",
			validate: function( value ) {
				if (isNaN(value)) {
					return 'Please enter a valid item_id!';
				} else {
					return true;
				}
			}
		}
	]).then(function(answers) {
		// do something with results and answers
	});
}

function selectAllProducts() {
	cnx.query("Select * from products", function(err,res) {
		if(err) throw err;
		for (var i in res) {
			var product = new Product(res[i].item_id, res[i].product_name, res[i].product_sales, res[i].department_name, res[i].price, res[i].stock_qty);
			products.push(product);
		};
		var columns = columnify(products);
		console.log(columns);
		// you displayed the columns/results, ask your question now :
		questions(res);
	});
};

Open in new window

Thank you Julian for helping out. I was able to get it working with a few mins to spare. We had to use inquirer as that is the only way we have learned so far to prompt the user.

Thanks,
Ed