node.js Trying to set multiple variables from multiple requests - node.js

So I've been trying to set a global variable from inside a request, but seem to be getting nothing. The code I'm using
A username for testing is test2 after username=
var forSearching = "test2";
var name = "";
console.log(forSearching);
request("http://mercsystem.esy.es/get.php?username=" + forSearching, function(err, res, body)
{
if (err) return console.error(err);
var main = JSON.parse(body);
if (main.success == "false")
{
message.reply("Sorry, invalid user!")
}
else
{
name = main.Username
}
});

If you insert a console.log(name) right after you set the value, you will see that the value is set just fine.
The issue is likely one of timing. request() is an asynchronous operation. That means calling request() starts the asynchronous operation, then the rest of your code continues to run to completion and then, some time LATER, the callback gets called with the final asynchronous results.
Though you don't show where you are trying to use the name variable, you are probably checking the value of this global variable before the callback has been called and thus before the value has been set.
In node.js, what you are doing is not how you use asynchronous results. It will never work reliably (or at all). Instead, the only place to use your asynchronous result is in the callback itself or in some function you call from the callback and pass the result to.
var forSearching = "test2";
console.log("begin");
request("http://mercsystem.esy.es/get.php?username=" + forSearching, function (err, res, body) {
console.log("in request() callback");
if (err) return console.error(err);
var main = JSON.parse(body);
if (main.success == "false") {
message.reply("Sorry, invalid user!")
} else {
var name = main.Username
console.log(name); // value shows fine here
// use the name variable here or call some function and pass
// the name variable to it
}
});
console.log("after request() call");
// You cannot use the name value here (even if it was in a global) because
// the async callback has not yet been called
If you ran this code with the console.log() statement I've added, you would see this sequence of events:
begin
after request() call
in request() callback
From this sequence, you can see that code after your request() call runs BEFORE the async callback runs. Thus, you cannot use your name variable there, even if it is in a global.

Related

Can't change the var value outside function

I need to change the value of result var, but I'm not getting.
My code:
var request = require('request');
var result = ""
function getQuote(callback){
return new Promise((resolve,reject) => {
request({'method': 'GET','url': 'https://blockchain.info/ticker'}, function (error, response) {
if (error) return reject(error);
return resolve(callback(response.body))
})
})
}
getQuote((data) => { result = data })
console.log(result) // return is empty
Thanks!
getQuote is an asynchronous function. When you call console.log(result), it may not call the callback function (data) => { result = data } you passed in while getQuote is still waiting for the response of your request. So, result is still the initialized value which is empty string.
try to log the result after the promise is fulfilled, such as getQuote((data) => { result = data }).then(()=>console.log(result))
Javascript engine will not wait for the promise to finish executing. Immediately after calling getQuote(), it will proceed executing the next line, i.e, console.log(result), which is simply empty and not yet assigned any value, because it will take some time to finish completing Promise-Get method.
You need to research and understand Javascript Execution Context and Event Looping.
https://blog.bitsrc.io/understanding-asynchronous-javascript-the-event-loop-74cd408419ff

Node.js request function return data

I have gone through questions about returning data from a node JS request call. A common mistake is assuming statements are executed line by line or synchronously, which is not the case here. A question of this type: How to get data out of a Node.js http get request.
My question is a bit different. I have written a function getNumber() which returns the number of results for given query. I am wondering how I return a value retrieved by the callback function? So for instance:
function getNumResults() {
Request(url, function(response) {
var responseJSON = JSON.parse(body);
return(responseJSON.results.count);
});
}
function Request(URL, callback) {
request(URL, function(error, response, body) {
console.log('URL: ', URL);
console.log('error: ', error);
console.log('statusCode: ', response && response.statusCode);
console.log('body: ', body);
callback(body);
});
}
What if I want getNumResults() to return responseJSON.results.count? How could I do this?
What if I want getNumResults() to return responseJSON.results.count? How could I do this?
You can't directly return an async value from getNumResults(). You just can't. The function returns long before the value is even available. It's a matter of timing. That's how async responses work. They finish some indeterminate time in the future, but they are non-blocking so the rest of your Javascript continues to run and thus the function returns before the result is even available.
The ONLY way to get the result out is with a callback of some kind. That applies to both your Request() function and to our getNumResults() function. Once a result is asynchronous, nobody in the calling chain can escape that. Async is infectious and you can never go from async back to synchronous. So, if your getNumResults() wants to get the value back to its caller, it will either have to accept a callback itself and call that callback when it gets the value or it will have to return a promise that is resolved with the value.
Here's how you could do this using promises (which are the future of async development in Javascript):
// load a version of the request library that returns promise instead of
// taking plain callbacks
const rp = require('request-promise');
function getNumResults(url) {
// returns a promise
return rp(url).then(body => {
// make the count be the resolved value of the promise
let responseJSON = JSON.parse(body);
return responseJSON.results.count;
});
}
Then, you would use getNumResults() like this"
getNumResults(someURL).then(count => {
// use the count result in here
console.log(`Got count = ${count}`);
}).catch(err => {
console.log('Got error from getNumResults ', err);
});
FYI, I think you can also get the request() library to parse your JSON response for you automatically if you want by setting an appropriate option {json: true}.
EDIT Jan, 2020 - request() module in maintenance mode
FYI, the request module and its derivatives like request-promise are now in maintenance mode and will not be actively developed to add new features. You can read more about the reasoning here. There is a list of alternatives in this table with some discussion of each one. I have been using got() myself and it's built from the beginning to use promises and is simple to use.

what is function (err, results) { in the below?

I am starting with nodejs and read basics on callback, here i have a code,
exports.handler = (event, context, callback) => {
var bx = require('barcode-js');
// Set default values.
var params = {
input: './1.bmp',
type: 'qrcode'
};
bx.analyze(params, function (err, results) {
if (err) {
callback('There was an error processing this image: ' + err)
}
results.forEach(function(result) {
callback(null,'Result type :' + result.type + '\t'+'Value: '+result.value);
});
});
};
what is happening bx.analyze(params, function (err, results) { in this line. why can't we just use bx.analyze(params) ?
The second parameter is function. Called a callback.
When you execute an async function, you can't wait for its returned value:
var result = bx.analyze(params); //you can't do this
So you tell the function that when it finishes its job, just call the callback (the function you passed as second parameter).
//so `analyze()` will call your passed function rather than `return` the result
//`err` will contain the error object if anything wrong happened in the analyze() function
//`results` will contain result if everything was fine
bx.analyze(params, function (err, results) {
if (err)
callback('There was an error processing this image: ' + err)
});
I strongly recommend you to learn how async code works in javascript. You can't learn Nodejs untill then..
Update:
In your code, the function handler is an async function so it takes a callback as a parameter (Just like analyze()).
When this function done with its job, it calls the callback.
Now in your code, it is called 2 times:
1) When an error occured, this function will call the callback and pass the error into it:
if (err) {
callback('There was an error processing this image: ' + err); //its passing "err" returned from analyze()
}
2) When everything goes well, it passes result set:
callback(null, 'Result type :' + result.type + '\t'+'Value: '+result.value); //the 1st parameter is being passed as "null" because there is no error in it, and second parameter passes the result
This is callback function which make the code asynchronous.
Means you are passing a function as argument to your bx.analyze(params) method. This callback method is executed once your bx.analyze(params) is finished, so its not blocking the other code, making the code asynchronous.
If you need how this call back is executed , then you have to look for Event loop, search it in Google,have lots of documentation.
if we use bx.analyze(params) then it is blocking (synchronous) code. event loop stop until bx.analyze(params) did not return any value and
there is no error handling.
if we use bx.analyze(params, function (err, results) { }); then it is asynchronous (non-blocking) code. event loop will not wait for returning value it goes to next statement and when bx.analyze(params, function (err, results) { return the callback event loop process it.
There is error handlation is also done
for deep understanding see this video https://www.youtube.com/watch?v=8aGhZQkoFbQ

Node.js: Continuous execution from settimeout when expecting node to do nothing until settimeout interval over

I'm writing a notifier for 3 deal of the day websites in node. I go and parse the body of the webpage to grab the details. In the details there is a timer for the how long the deal will last. I'm reading that timer and trying to use setTimeout/setInterval to set when the function should execute again. However the function calls are continuous instead of waiting.
Pseudo code of what I'm doing:
var getData = function(url) {
request(url, function(err, resp, body){
if(err) throw err;
//process the body getting the deal information and timer
setTimeout(getData(url),timer*1000);
}
getData(url1);
getData(url2);
getData(url3);
Full code here.
I want the program to run, continually calling itself with the new timeouts for the webpages.
I'm a Node.js newbie so I'm guessing I'm getting tripped up with the async nature of things.
Any help is greatly appreciated.
EDIT:
more simply :
var hello = function(){
console.log("hello");
setTimeout(hello(),25000);
}
hello();
prints out hello continuously instead of hello every 2.5s. What am I doing wrong?
The problem is evident in your hello example, so lets take a look at that:
var hello = function(){
console.log("hello");
setTimeout(hello(),25000);
}
hello();
In particular this line: setTimeout(hello(),25000);. Perhaps you are expecting that to call hello after a 25 second timeout? Well it doesn't, it calls hello immediately, (that's what hello() does in Javascript, and there is nothing special about setTimeout), and then it passes the return value of hello() to setTimeout, which would only make sense if hello() returned another function. Since hello recursively calls itself unconditionally, it doesn't ever return, and setTimeout will never be called. It's similar to doing the following:
function hello() {
return doSomething(hello());
}
Is it clear why doSomething will never be called?
If you want to pass a function to setTimeout, just pass the function itself, don't call it and pass the return value: setTimeout(hello, 25000);.
Your fixed code:
var getData = function(url) {
request(url, function(err, resp, body){
if(err) throw err;
//process the body getting the deal information and timer
setTimeout(getData, timer*1000, url);
});
};
getData(url1);
getData(url2);
getData(url3);
Noticed that I passed the argument for getData as a third argument to setTimeout.
What's happening is 'request' is being run as soon as getData is called. Do you want getData to be the function you call to start the timer, or the one that loads the data?
var getData = function(url) {
function doRequest(url) {
request(url, function(err, resp, body) {
if(err) throw err;
//process the body getting the deal information and timer
}
setTimeout(doRequest(url),timer*1000);
}
getData(url1);
getData(url2);
getData(url3);
What you want is 'setTimeout' to point to a function (or anonymous function/callback) that you run after the timer expires. As you originally wrote, getData was immediately calling request (and then calling getData again after your timer)

NodeUnit testing mysql function test always successful

I'm trying to learn how to use NodeUnit to test my NodeJs code. Ive written the following code, however each time I run the test, the result is OK: 0 assertions, no matter whether the input parameter is valid or not. Can anyone explain why this doesn't work and how I can fix it?
auth.class.js: This function accepts a user ID and returns a username.
exports.username = function(uid, callback) {
db.query('SELECT username FROM ul_logins WHERE id=?', uid, function(err, results){
if (err) throw new Error(err);
if(results.length > 0)
{
callback(null, results[0].username);
}
else
throw new Error("No results.");
});
};
authtest.js: This test will run successful every time, no matter what the uid is, and count 0 assertions.
var auth = require('./auth.class.js');
exports['username'] = function (test) {
auth.username(1, function(err, data){
return test.equal(data, "joe#example.com");
});
test.done();
};
The function you are testing is asynchronous (see the rewritten function below). You need to put the test.done() in the callback function:
exports['username'] = function (test) {
test.expect(2);
auth.username(1, function (err, data) {
test.ifError(err);
test.equal(data, 'joe#example.com');
test.done();
});
};
In your version, test.done gets called before the callback to auth.username is called. Use test.expect to tell nodeunit how many asserts it should receive before test.done is called.
You have a serious problem in your auth.username function. You should not throw in asynchronous code since a try-catch cannot be used to catch the error, leading to uncaught exceptions. You should always pass errors in asynchronous code to a callback as the first argument (convention). Your function should look like:
exports.username = function (uid, callback) {
var query = 'SELECT username FROM ul_logins WHERE id=?';
db.query(query, uid, function (err, results) {
if (err) {
return callback(err);
}
if (results.length === 0) {
return callback(new Error('No user found.'));
}
callback(null, results[0].username);
});
};
Note that errors are handled first (keeps the code neat), and callback calls in the branches are returned to avoid calling the callback multiple times (using else adds a level of indentation).
I get the impression that you are new to Node, and I remember having difficulty over this point too. Consider any function that does something over the network as asynchronous. This could take a long time, so to avoid blocking the process Node gets the OS to handle the task, and takes a callback to call at some point in the future when the OS gives it a result. This is why Node relies so heavily on callbacks. It leaves the Node process free to do other things (like call test.done in your question) while it waits. It also means that try-catch (which can only catch errors thrown in the same 'tick') no longer works. The conventional way to handle errors is to call the callback with the error as the first argument. All other arguments are for actual results.

Resources