How to use child-process-promise - javascript

var promise = require('child-process-promise').spawn;
promise('some_command_producing_output')
.then(function (result) {
...
})
.catch(function (err) {
...
});
What I want is to add some processing after command produced output in stdout. So finally I want to create a function to use like this:
RunCommandAndProcess('some_command_producing_output')
.then(function (result) {
...
})
.catch(function (err) {
...
});
The function should use promise from child-process-promise, wait until successful result produced and return promise for processing data.

Welcome to Stack Overflow #ScHoolboy.
I cansuggest you use a basic child-process module from Node.js and promising it yourself in the following way
const spawn = require('child_process').spawn;
const spawnPromise = (cmd, args) => {
return new Promise((resolve, reject) => {
try {
const runCommand = spawn(cmd, args);
runCommand.stdout.on('data', data => resolve(data.toString()));
runCommand.on('error', err => {
throw new Error(err.message);
});
} catch (e) {
reject(e);
}
});
};
Where:
cmd - command, for example, "echo"
args: array of arguments, for example ["Hello world"]
You can call the function as RunCommandAndProcess if you need :)
Example of usage:
spawnPromise('ls', ['-la']).then(data => console.log('data: ', data));
Or
const result = await spawnPromise('ls', ['-la']);

You can do it by
var spawn = require('child-process-promise').spawn;
var promise = spawn('echo', ['hello']);
var childProcess = promise.childProcess;
console.log('[spawn] childProcess.pid: ', childProcess.pid);
childProcess.stdout.on('data', function (data) {
console.log('[spawn] stdout: ', data.toString());
});
childProcess.stderr.on('data', function (data) {
console.log('[spawn] stderr: ', data.toString());
});
promise.then(function () {
console.log('[spawn] done!');
})
.catch(function (err) {
console.error('[spawn] ERROR: ', err);
});
For the more information please check the documentation

Related

Console log promise nodejs

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.
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.

return result from memcached.get()?

I am using npm memcached package https://www.npmjs.com/package/memcached
It is possible to return data from memcached get method?
Now return data is undefined/
memcached.set('foo', 'bar', 10, function (err) { });
let data1;
memcached.get('foo', function (err, data) {
console.log(data); // bar
data1 = data
});
console.log(data1); // undefined
let data2 = memcached.get('foo', function (err, data) {
console.log(data); // undefined
return data;
});
console.log(data2); // undefined
let data3 = async () => {
let result = await memcached.get('foo', function (err, data) {
console.log(data); // bar
});
console.log(result); // undefined
return result;
}
console.log(data); // {}
You can't return from get() as it's an asynchronous callback. What you can do is:
with callbacks:
memcached.get('foo',(err, data) => {
if(err) {
console.log('error: ', err);
} else {
console.log('data: ', data);
}
});
with promises:
memcached.get('foo')
.then((data) => {
console.log('data: ', data);
})
.catch((err) => {
console.log('error: ', err);
});
and with async/await:
const getData = async () => {
try {
const data = await memcached.get('foo');
console.log('data: ', data);
} catch (err) {
console.log('error: ', err);
}
}
hope this helps :)
Since memcached is async you can't really return from it, altho I see OP found a way via a promisify wrapper. What you can do is call another function from inside the callback.
Working with async socket communication I've had to split up a lot of my workflows into request and receives.
memcached.get('foo',(err, data) => {
doStuff(data);
});
function doStuff(data) {
//do some stuff here
}
Of course you could always do your work with the data inside the handler too. But in some cases that isnt the best approach.

If I'm using a Promise.all to call a lambda.invoke, does the invocation type matter

If I use a Promise.all and map() to call a lambda.invoke, will the InvocationType of Event vs RequestResponse even matter?
Won't it still be running the invokes in parallel?
function get1(id) {
return new Promise((resolve, reject) => {
const params = {
FunctionName: 'myLambda', // the lambda function we are going to invoke
InvocationType: 'RequestResponse',
Payload: { id },
};
lambda.invoke(params, (err, data) => {
if (err) {
reject(new Error('error'));
} else {
const result = JSON.parse(data.Payload);
resolve(result);
}
});
}).catch(e => Promise.resolve({ error: 'Error has occurred.' }));
}
exports.getDetails = list => Promise.all(list.map(get1))
.then((response) => {
return result;
}).catch((error) => {
console.log('oops ', error);
});

Returning a bluebird promise to electrons renderer process

Im using Electron's remote function to call a node module which returns a bluebird promise. However, I can't figure out how to get the promise returned back to the renderer process thats calling the module.
Using this code the value of return_data1 is always empty.
exports.call_python = function () {
data1 = []
var Promise = require('bluebird');
var exec = require('child_process').execFile;
function promiseFromChildProcess(child) {
return new Promise(function (resolve, reject) {
child.addListener("error", reject);
child.addListener("exit", resolve);
});
}
var child = exec('ls');
promiseFromChildProcess(child).then(function (result) {
console.log('promise complete: ' + result);
}, function (err) {
console.log('promise rejected: ' + err);
});
child.stdout.on('data', function (data) {
console.log('stdout: ' + data);
data.push={data: data}
});
child.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
child.on('close', function (code) {
console.log('closing code: ' + code);
});
return data1
};
Once you jump into Promises it's pretty much promises all the way down. You can unwrap a Promise to get back to callback semantics but unless you are writing a service for pre-Promise API why would you?
In this case don't return data1; return the resolved promise. e.g.:
return promiseFromChildProcess(child).then(function (result) {
console.log('promise complete: ' + result);
return result;
}, function (err) {
console.log('promise rejected: ' + err);
return '';
});
or if the client should deal with the error just:
return promiseFromChildProcess(child);
It sounds like maybe you are unsure of how to use child_process. The really simple way is to just grab stdout after the child process exits:
var b = require('bluebird');
var cp = require('child_process');
new b(function(resolve, reject){
cp.exec('dir', function(err, stdout, stderr){
resolve(stdout);
});
}).then(function(data){
console.log("dir is "+data);
});
so do:
exports.call_python = function () {
var b = require('bluebird');
var cp = require('child_process');
return new b(function(resolve, reject){
cp.exec('ls', function(err, stdout, stderr){
resolve(stdout);
});
});
};

Nodejs rest service

I am trying to create REST service using Nodejs and Mysql.
his is my code:
var sqlDb = require("mysql");
var settings = require("../settings");
exports.executeSql = function (sql, callback) {
var conn = sqlDb.createConnection(settings.dbConfig);
conn.connect()
.then(function () {
var req = new sqlDb.Request(conn);
req.query(sql)
.then(function (recordset) {
callback(recordset);
})
.catch(function (err) {
console.log(err);
callback(null, err);
});
})
.catch(function (err) {
console.log(err);
callback(null, err);
});
};
But I have an error
.then(function(){
^
TypeError: cannot read property 'then' of undefined
Can anybody help me to solve this problem?
The correct function is createConnection. Read the docs please:
https://www.npmjs.com/package/mysql#introduction
In the documentation, the connect method is not returning a promise if you look at the documentation this can work as callback method:
var connection = mysql.createConnection({
host : 'example.org',
user : 'bob',
password : 'secret'
});
//** Look here...
connection.connect(function(err) {
if (err) {
console.error('error connecting: ' + err.stack);
return;
}
console.log('connected as id ' + connection.threadId);
});
As a good alternative, you can use the package promise-mysql that is using bluebird and you can locate here (which I strongly suggest to use) or you can wrap it up in a promise like using bluebird like:
async function connect(connection) {
return new Promise((resolve, reject) => {
connection.connect((err) => {
return err ? reject(err) : resolve(connection);
})
});
}

Categories

Resources