How to wait for a asynchronous function to finish it's execution in nodejs
Solution 1
You could use a Promise
.
function daemonGetNodeStatus(kubeURL, nodeName) {
console.log(nodeName);
var request = require("request");
var options = {
method: 'GET',
url: kubeURL+'/api/v1/nodes/'+nodeName+'/status',
headers: {
'Cache-Control': 'no-cache',
'Authorization': 'Bearer '+constants.accessToken
}
};
return new Promise((resolve, reject) => {
request(options, function(error, response, body) {
if (error)
reject(new Error(error));
var bodyJSON = JSON.parse(body);
var result = [];
var temp = {};
for (var i = 0; i < bodyJSON.status.conditions.length; i++) {
if(bodyJSON.status.conditions[i].status == "True") {
result.push(bodyJSON.status.conditions[i].type);
}
}
resolve(result);
});
}
daemonGetNodeStatus(url, name).then(result => {
console.log(result);
}).catch(err => {
console.log(err);
});
Solution 2
function daemonGetNodeStatus(kubeURL, nodeName, callback) {
console.log(nodeName);
var request = require("request");
var options = {
method: 'GET',
url: kubeURL+'/api/v1/nodes/'+nodeName+'/status',
headers: {
'Cache-Control': 'no-cache',
'Authorization': 'Bearer '+constants.accessToken
}
};
request(options, function(error, response, body) {
if (error)
{
callback(error);
} else {
var bodyJSON = JSON.parse(body);
var result = [];
var temp = {};
for (var i = 0; i < bodyJSON.status.conditions.length; i++) {
if(bodyJSON.status.conditions[i].status == "True"){
result.push(bodyJSON.status.conditions[i].type);
}
}
callback(null, result);
}
});
}
One of the best things about Node is it's asynchronous. It might be hard to understand in the beginning, but once you know, it's the best thing. It's also the reason Node is so fast.
So, when you have to run an asynchronous function, you also send an extra function to the asynchronous function called a callback function which will be executed once the async operation is done. The above code illustrates this.
Then you can use the function like this:
daemonGetNodeStatus('http://kube.com/something', 'name', function(err, result){
if(err) {console.log(err); }
else {
console.log(result);
// do whatever you want with the async result
}
});
Solution 3
I'd like to answer with one more approach - async\await
. If you have NodeJS v8 installed, better to stick with async\await
.
Also, I made some improvements, feel free to ignore them if you don't like it.
1) async/await
offers to you more convenient way to write and deal with asynchronous code. Instead of callbacks or Promise chains, you just write await
.
2) Instead of iterating through array via for-loop
you can use filter
and map
to find all the k8s conditions where status is True.
3) json
field in request
options will parse response as JSON and returns to you already parsed JSON value.
const request = require("request-promise");
async function daemonGetNodeStatus(kubeURL, nodeName) {
const options = {
json: true,
method: 'GET',
url: kubeURL + '/api/v1/nodes/' + nodeName + '/status',
headers: {
'Cache-Control': 'no-cache',
'Authorization': 'Bearer '+constants.accessToken
}
};
const response = await request(options);
return response.status.conditions.filter(cond => cond.status === 'True').map(cond => cond.type);
});
UPD
Any async
function returns Promise, so you need to await it or call it with then\catch
:
async function someAnotherAsyncFunction() {
const types = await daemonGetNodeStatus('KUBE_URL', 'NODE_NAME');
// do something with types
}
or
daemonGetNodeStatus.then(types => doSomethingWithTypes(types)).catch(error => doSomethingWithError(error));
Light Yagami
Updated on June 05, 2022Comments
-
Light Yagami almost 2 years
I have a function that returns a value which it gets from an http GET request in nodejs. How do I wait for the async request function to finish and return the result from the function that generates the request. I have checked async library in npm, but that doesn't solve my problem. Thanks for the help!!
function daemonGetNodeStatus(kubeURL, nodeName) { console.log(nodeName); var request = require("request"); var options = { method: 'GET', url: kubeURL+'/api/v1/nodes/'+nodeName+'/status', headers: { 'Cache-Control': 'no-cache', 'Authorization': 'Bearer '+constants.accessToken } }; request(options, function(error, response, body) { if (error) throw new Error(error); var bodyJSON = JSON.parse(body); var result = []; var temp = {}; for (var i = 0; i < bodyJSON.status.conditions.length; i++) { if(bodyJSON.status.conditions[i].status == "True"){ result.push(bodyJSON.status.conditions[i].type); } } console.log(result); });
};
-
Faizuddin Mohammed about 6 yearsYou won't return value. You handle it in an async way.
-
-
jfriend00 about 6 yearsYou need to explain that this returns a promise and the caller has to use
.then()
on that promise to get the value. Though it looks that way in the code, this does not return the value directly. functions tagged asasync
always return a promise. -
Eugene Obrezkov about 6 yearsYou're right, this case should be explained explicitly. I''l update the answer in a while.
-
jfriend00 about 6 yearsAnd, because there's only one async operation here, this case isn't really made any simpler by using
await
. The operative change you made was switching to therequest-promise
library. With that you could have just donereturn request(...).then(...)
.