Request callback does not get called until end - node.js

Why is Request callback not called at all in this example?
Output of this would be:
here
now here
"did it!" or any log commands in callback does not get called.
var request = require('request');
d=0;
console.log("here");
request('http://www.google.com', function (error, response, body) {
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
console.log('body:', body); // Print the HTML for the Google homepage.
d=1;
});
console.log("now here");
while(d==0){}
console.log("did it!");
If I remove "while(d==0){}". Then it gets called.

you actually stuck in while(d==0){} because you are making async code with sync
The async code fires in the event loop so the flow of the application going with the sync code which will fire the while loop and start iterate.

Your process is stuck in an endless loop.
Replace your d=1 in the callback with console.log("did it!"), and get rid of the while loop.
(ie. everything you want to run after the response is returned, you should put inside the callback function)

The problem is your while is starving the main thread, the callback passed to request will never be executed since the main flow will never finish execute, I'd suggest you to study a little bit of the event loop of node.js.
This while loop starves the event loop by running
infinitely, greedily checking and rechecking a value that is never given a chance
to change, as the event loop is never given a chance to schedule your request callback
for execution.

Related

Using 'body' returned from Request

I am using https://github.com/request/request.
The example that is given is:
const request = require('request');
request('http://www.google.com', function (error, response, body) {
console.error('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
console.log('body:', body); // Print the HTML for the Google homepage.
});
How can I use body elsewhere in my code? I want something like return body but nothing works. I can't use it anywhere!
You cannot directly return an asynchronous result from outside the request() callback. This is not unique to this particular function, but is how all asynchronous callbacks work in Javascript.
When you call request() it starts an asynchronous operation and turns it over to native code. The JS interpreter then goes about it's merry way executing the rest of your Javscript after this function call (not in the callback, but after that). So, you should be able to immediately see that the body result does not exist yet, but the rest of your Javascript is already executing.
Then, some indeterminate time later (depending upon how responsive the server is that you're contacting and how big the result is), when the JS interpreter has nothing else to do, the callback gets called and the body result is available.
So, the ONLY place in your code that you know the body result is good and is available is INSIDE that callback. So, the general way of programming with an asynchronous operation like this in Javascript is that you use the result inside the callback. Any code that needs to use that result gets put inside that callback or you can put the code in a separate function and call that function from inside the callback and pass the body result as an argument to the function.
If you wanted to wrap this request in a function and communicate back that result to the caller (which is not exactly what you show here, but another way to write the code), I'd suggest you first read How do I return the response from an asynchronous call? because it outlines the various ways you can communicate back the body result from your asynchronous operation (another callback or use promises).
To many newbie Javascript developers this seems somewhat heretical. What do you mean I can't just call a function, get the result and return it from the function? Well, that's the extra complication with Javascripts non-blocking, asynchronous I/O model that is entirely event driven. Once you get down the learning curve, you will find a huge number of advantages in the language that flow from this architectural model, but you will have to deal with this extra complication.
The language is evolving to make this type of programming simpler with the use of promises in async functions and then the use of await to "wait" on a promise. If you use the request-promise library instead of the request library (request-promise is derived from request), then you can deal with a promise as the return value and you have more options.
const rp = require('request-promise');
async getMeSomeData() {
try {
let body = await rp('http://www.google.com');
console.log(body);
// can put code here that uses body
return body; // becomes the resolved value of the returned promise
} catch(err) {
console.log(err);
throw err; // makes sure the returned promise is rejected
}
});
getMeSomeData().then(body => {
// use the body here
}).catch(err => {
// error here
});
Note: I showed possibly using the body value or err inside getMeSomeData() or at the caller. Usually, you would do one or the other, but I wanted to show both ways.

Function does not wait until Promise is resolved

I'm developing a simple discord bot and I am attempting to print some general data about a certain player. I recently learned about async/await and I attempted to implement it into my code. It does not seem to work however because when I first trigger this code, it prints null but on subsequent triggers it will print the correct data, indicating that my function did not wait for the Promise to resolve.
async function stats(){
data = await NBA.stats.playerInfo({ PlayerID: curry.playerId });
}
stats();
data = JSON.stringify(data);
console.log(data);
The variable data is a global variable declared at the top of my program and initially initialized to null.
If I understand your intention correctly, what you want is to asynchronously fetch some data into data and then display it on the console.
Your implementation of stats is doing the fetch correctly. But your problem is, the part where you log to console has no dependence on the fetch being completed.
When you call a function that has been declared async, you are saying that you want it to execute "in the background" so to speak. The interpreter won't wait for that function to finish executing.
stats(); // begin executing this function
data = JSON.stringify(data); // but don't wait for it to finish before moving on to this line
console.log(data);
Clearly, that's not what you want. Instead, you want to wait for stats to finish what it's doing before logging data. stats being an async function returns a Promise, so you can do this:
function logData() {
console.log(JSON.stringify(data));
}
stats().then(logData);

Getting a JSON from a website Node JS

So I'm fairly new to node js, and am having trouble wrapping my head around asynchronous programming. I'm trying to get a JSON from a website and pass it to a variable for use later, to test I have been using this code:
var https = require("https");
var a;
function getter(url){
var request = https.get(url, function(response){
var body = "";
response.on("data", function(chunk){
body += chunk;
});
response.on("end", function(){
if(response.statusCode === 200){
try{
a = JSON.parse(body);
}catch(err){
console.log(err);
}
}
})
})
};
getter('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY');
console.log(a);
When I run this I get a as undefined, which seems to make sense from what I've read. But I'm unclear as to what to do from here. How would I go about passing this JSON into a variable?
http.get is asynchronous and executes the event handlers when the events occur. When you call getter() this function immediately returns, ie it does not wait for the events and the next statement console.log(a) is executed.
Furthermore, js is single threaded, and the current execution stack is never interrupted for any other event/callback or whatsoever. So the event handlers can only run if the current execution has come to an end, ie contains noch more statements. Thus, your console.log() will always be executed before any eventhandler of the request, thus a is still undefined.
If you want to continue after the request finished, you have to do it from the eventhandler.
See this excellent presentation for some more details https://youtu.be/8aGhZQkoFbQ

An if statement will execute synchronous before a callback?

I have to change the value of an json element, if it exists, before making an async function call, but I'm not sure if this code will execute in the order that I want. Here is a simple example:
function first_function(json, callback) {
get_only_valid_elements_json(json, function(valid_json) {
if (valid_json.element) {
valid_json.element = something;
}
update_something(valid_json, function(error) {
if (error) {
return callback(error);
} else {
return callback({success:"YAY"});
}
});
});
}
I would like to know how the following code will execute and more important why. Thanks!
It looks right to me.
Assuming get_only_valid_elements_json, and update_something call the function passed to them when they're finished with their job, this is how it is executed:
it calls get_only_valid_elements_json, and first_function function returns
when get_only_valid_elements_json finishes (i.e. when it calls the callback function passed in the second argument), it will execute the if statement, and conditionally, its block
then, update_something is called and then function(valid_json) {...} returns
when update_something finishes (i.e. calls the callback function), it will execute the if (error) statement and the appropriate block
the callback function is called (either with error or success), signalling that get_only_valid_elements_json finished its job
So the functions synchronously return before their "real job" is done.
The reason for asynchronous calls is to not block the executing process when you're waiting for something, e.g. a response to an AJAX call. You just tell the browser to execute a given function when the response is received, so when it receives the response it calls the function you gave to the AJAX call, which calls the function given to update_something, which then calls the callback given to first_function.

node.js setImmediate unexpected behavior

As I understand, the differences between process.nextTick() and setImmediate() are the followings:
callbacks scheduled by process.nextTick() will ALL be executed before entering the next event loop, while callbacks scheduled by setImmediate() will only be executed ONE per event loop.
Base on the characteristics stated above, it can be said that: recursive call of process.nextTick() can cause the program to hang up, while recursive call of setImmediate() will not.
Then I've written some testing code to verify the statements above, here is my code:
process.nextTick(function() {
console.log('nextTick1');
});
process.nextTick(function() {
console.log('nextTick2');
});
setImmediate(function() {
console.log('setImmediate1');
process.nextTick(function() {
console.log('nextTick3');
});
});
setImmediate(function() {
console.log('setImmediate2');
});
My expected result should be
nextTick1, nextTick2, setImmediate1, nextTick3, setImmediate2
, but what I actually got is
nextTick1, nextTick2, setImmediate1, setImmedate2, nextTick3
Then I've run another test to study the behavior of setImmediate():
//the following code is using express as the framework
app.get('/test', function (req, res) {
res.end('The server is responding.');
});
app.get('/nexttick', function (req, res) {
function callback() {
process.nextTick(callback);
}
callback();
res.end('nextTick');
});
app.get('/setimmediate', function (req, res) {
function callback() {
setImmediate(callback);
}
callback();
res.end('setImmediate');
});
Step1: I accessed http://localhost:3000/nexttick on my browser and I got the text nexttick.
Step2: I accessed http://localhost:3000/test to test if my server is still responding to requests, and I didn't get any response, the browser kept waiting for response. This is nothing surprising because the recursive call of process.nextTick() had hanged up the server.
Step3: I restarted my server.
Step4: I accessed http://localhost:3000/setimmediate and got the text setimmediate
Step5: I accessed http://localhost:3000/test again to test if my server is still responding. And the result is as the same as Step2, I didn't get any response and the browser kept waiting for response.
This means the behavior of process.nextTick() and setImmediate() is pretty much the same but as I know they are not.
I was wondering why is this happening or have I misunderstood sth. Thank you.
P.S. I am running Node v0.12.7 under Windows 10.
Actually your test results looks ok (I only refer to the first test).
Your comments "setImmediate() will only be executed ONE per event loop." is wrong, See https://nodejs.org/api/timers.html#timers_setimmediate_callback_arg
and thats the reason you don't understand the first test results.
Basically process.nextTick will put your function at the end of the current event loop while setImmediate will put it at the next event loop.
But executing multiple setImmediate is ok and they will all go to that same next event loop.
In
setImmediate(function() {
console.log('setImmediate1');
process.nextTick(function() {
console.log('nextTick3');
});
});
setImmediate(function() {
console.log('setImmediate2');
});
Basically you have put 2 function sthat will be invoked in next event loop, and in one of them you put another nextTick which will be invoked at the end of that same cycle but at the end of that same cycle.
So it will first invoke those 2 setImmediate and than the nextTick that was called in the first.

Resources