How to wait for a asynchronous function to finish it's execution in nodejs

10,206

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));
Share:
10,206
Light Yagami
Author by

Light Yagami

Updated on June 05, 2022

Comments

  • Light Yagami
    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
      Faizuddin Mohammed about 6 years
      You won't return value. You handle it in an async way.
  • jfriend00
    jfriend00 about 6 years
    You 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 as async always return a promise.
  • Eugene Obrezkov
    Eugene Obrezkov about 6 years
    You're right, this case should be explained explicitly. I''l update the answer in a while.
  • jfriend00
    jfriend00 about 6 years
    And, 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 the request-promise library. With that you could have just done return request(...).then(...).