Home > Mobile >  Console log promise nodejs
Console log promise nodejs

Time:11-22

How can I console.log the promise stored in a promise variable? I want to later assign that to a variable.

   function getMetricFilters() {
      const promise = new Promise(function(resolve, reject) {

          exec("aws cloudwatch list-metrics --namespace AWS/ApiGateway  | jq -r .Metrics[].Dimensions[].Name | sort -u", (error, stdout, stderr) => {
              if (error) {
                  console.error(`error: ${error.message}`);
                  //return errorResponse(500, 'Error running migration.');
              }
              if (stderr) {
                  console.log(`stderr: ${stderr}`);
                  //return errorResponse(500, 'Error running migration.');
              }
              console.log(`stdout: ${stdout}`);
              //return okResponse(200, 'Migration successfully.');
            })
      })

      return promise
  }

   getMetricFilters() // I want the result of promise to be printed out or store it in a variable.

If I don't use the getMetricFilters function then it prints out stdout value. But if use the function, then nothing is printed out.

Full code:

var AWS = require('aws-sdk');
AWS.config.region = 'ap-south-1';
var lambda = new AWS.Lambda();
const exec = require("child_process").exec;

exports.handler = function(event, context, callback) {
   console.log("AWS lambda and SNS trigger ");
   console.log(event);

    const promise = new Promise(function(resolve, reject) {

        exec("ls /usr/bin/", (error, stdout, stderr) => {
            if (error) {
                console.error(`error: ${error.message}`);
                //return errorResponse(500, 'Error running migration.');
            }
            if (stderr) {
                console.log(`stderr: ${stderr}`);
                //return errorResponse(500, 'Error running migration.');
            }
            console.log(`stdout: ${stdout}`);
            //return okResponse(200, 'Migration successfully.');
          })
    })

   return promise // Right now it ends here. But I intened to do other things instead of return and end here.
   
   var sns = JSON.parse(event.Records[0].Sns.Message);
   var sns_MetricName = sns.Trigger.MetricName;
   var sns_NameSpace = sns.Trigger.Namespace;
   
   console.log(sns.Trigger.Dimensions)
   
   function dimensionValue(name) {
       console.log("Testing")
       var dimensionsValue = sns.Trigger.Dimensions.find(dimension => dimension.name === name).value 
       return dimensionsValue
   }
   
   function dimensionName(name) {
       return sns.Trigger.Dimensions.find(dimension => dimension.name === name)
   }

  if (sns.Trigger.Namespace == "AWS/S3") {
      var sns_DimensionsValue = dimensionValue('BucketName')   '_'   dimensionValue('StorageType')
  }  
   

  
  console.log("Printing SNS DimensionsValue")
  console.log(sns_DimensionsValue)
  



   var zabbix_Hostname = JSON.stringify(sns_NameSpace.replace("/", "_"));
   var zabbix_Key = "AWS["   sns_DimensionsValue   '_'   sns_MetricName   "]"
   var zabbix_Key = JSON.stringify(zabbix_Key);
   
  
   console.log("Printing SNS")
   console.log(event.Records[0].Sns.Message)
   
  var params = {
    FunctionName: 'zabbixPy', // the lambda function we are going to invoke
    InvocationType: 'RequestResponse',
    LogType: 'Tail',
    Payload: `{ "Host": ${zabbix_Hostname}, "Key": ${zabbix_Key}, "Value": "1"}`
  };

  lambda.invoke(params, function(err, data) {
    if (err) {
      context.fail(err);
    } else {
      context.succeed('zabbixPy said '  data.Payload);
    }
  })
  
   console.log("End of function");
   
};

CodePudding user response:

Make a re-usable helper function that encapsulates exec() in a promise:

function execAsync(cmdline) {
    return new Promise((resolve, reject) => {
        exec(cmdline, (error, stdout, stderr) => {
            if (error) reject({error, stdout, stderr});
            else resolve({stdout, stderr});
        });
    });
}

Make a function for your cloudwatch command:

function getMetricFilters() {
    return execAsync("aws cloudwatch list-metrics --namespace AWS/ApiGateway  | jq -r .Metrics[].Dimensions[].Name | sort -u");
}

Use it:

getMetricFilters()
    .then(({stdout, stderr}) => {
        okResponse(200, 'Migration completed successfully.');
    })
    .catch(({error, stdout, stderr}) => {
        console.error(`error: ${error.message}`);
        console.log(`stdout: ${stdout}`);
        console.log(`stderr: ${stderr}`);
        errorResponse(500, 'Error running migration.');
    });

Mixing node-style callbacks and promises usually does not end well.

Since your exports.handler is a callback-based function, and all your other functions (like exec() and lambda.invoke()) are callback-based, I would keep the entire code callback-based.

The async module offers useful helpers for this, such as waterfall(), which executes a list of asynchronous functions one after another, passing the result(s) of the previous to the next.

exports.handler = function (event, context, callback) {
    async.waterfall([
        // 1. parse SNS message (throw if invalid/unexpected)
        (callback) => {
            const sns = JSON.parse(event.Records[0].Sns.Message);
            console.log(1, sns);
            const Namespace = sns.Trigger.Namespace;
            if (Namespace !== "AWS/S3") throw new Error('Unexpected Namespace: '   Namespace);
            const msgData = {
                Namespace: Namespace,
                MetricName: sns.Trigger.MetricName,
                BucketName: sns.Trigger.Dimensions.find(where('name', 'BucketName')).value,
                StorageType: sns.Trigger.Dimensions.find(where('name', 'StorageType')).value
            };
            callback(null, msgData);
        },
        // 2. run cloudwatch command
        (msgData, callback) => {
            console.log(2, msgData);
            const cmdline = "aws cloudwatch list-metrics --Namespace AWS/ApiGateway | jq -r .Metrics[].Dimensions[].Name | sort -u";
            exec(cmdline, (err, stdout, stderr) => {
                if (err) return callback(err);
                callback(null, msgData, stdout, stderr);
            });
        },
        // 3. run zabbixPy
        (msgData, stdout, stderr, callback) => {
            console.log(3, msgData, stdout);
            lambda.invoke({
                FunctionName: 'zabbixPy',
                InvocationType: 'RequestResponse',
                LogType: 'Tail',
                Payload: JSON.stringify({
                    Host: msgData.Namespace.replace("/", "_"),
                    key: `AWS[${msgData.BucketName}_${msgData.StorageType}_${msgData.MetricName}]`,
                    Value: "1"
                })
            }, callback);
        },
        // 4. next step...
        (zabbixResponse, callback) => {
            console.log(4, zabbixResponse.Payload);
            // ...
            callback(null, 'All done.');
        },
    ], (err, result) => {
        if (err) {
            console.error(err);
            context.fail(err);
            callback(err);
            return;
        }
        console.log(result); // 'All done.'
        // don't forget to call the main callback here
    });
};

The alternative would be to convert all asynchronous functions in that code path to promise-based functions. Not sure if that's less work.

  • Related