So I have this function in node.js that gets the external IP by grabbing it from https://icanhazip.com/ (handy website, check it out), but when the request is called it isn't allowed to finish before return is called. Here is the code:
var request = require('request');
var get_ext_ip = function(){
var _ip; //Initialize a return variable
//Launch an HTTPS request to a simple service that shows IP of client
//The callback function isn't allowed to finish.
request('https://icanhazip.com', function(error, response, body){
_ip = body; //when finished store the response in the variable that is going to be returned.
});
//Return
return _ip;
}
var ip = get_ext_ip();
console.log(ip); //undefined
So I guess, the question here is: how do I make this script wait for that callback function to finish before returning a value?
Take a look at the async series library here, sample here
async.series([
function(callback){
// do some stuff ...
callback(null, 'one');
},
function(callback){
// do some more stuff ...
callback(null, 'two');
}
],
// optional callback
function(err, results){
// results is now equal to ['one', 'two']
});
// an example using an object instead of an array
async.series({
one: function(callback){
setTimeout(function(){
callback(null, 1);
}, 200);
},
two: function(callback){
setTimeout(function(){
callback(null, 2);
}, 100);
}
},
function(err, results) {
// results is now equal to: {one: 1, two: 2}
});
Also, take a look at this question, Idiomatic way to wait for multiple callbacks in Node.js
That's because of the asynchronous nature of I/O requests in Node: the function get_ext_ip returns before the request has finished.
One of the methods of handling this is to pass a callback function which will get called when the request is done:
var request = require('request');
var get_ext_ip = function(callback) {
request('https://icanhazip.com', function(error, response, body) {
callback(error, body);
});
}
get_ext_ip(function(err, ip) {
if (err)
console.log('an error occurred:', error);
else
console.log(ip);
});