how to pass function output to another function - javascript

was playing around with casperjs lately and didnt manage to complete the below code, was using child_process and need to get function output to be passed to another function any ideas ?
success call variable scope limited to success function only, and i cant use it anywhere in my code
casper.repeat(3, function() {
this.sendKeys(x('//*[#id="text-area"]'), testvalue.call(this)); // testvalue.call(this) dosnt input anything here
})
casper.echo(testvalue.call(this)); // Print output successfully
function testvalue() {
var spawn = require("child_process").spawn
var execFile = require("child_process").execFile
var child = spawn("/usr/bin/php", ["script.php"])
child.stdout.on("data", function (data) {
console.log(JSON.stringify(data)); // Print output successfully
return JSON.stringify(data); // Problem is here i cant use Data any where in code except this scope
})
}

Since spawn is an asynchronous process, you need to use a callback for testvalue. Returning something inside the event handler doesn't return it from testvalue.
The other problem is that you need to remain in the CasperJS control flow. This is why I use testvaluedone to determine if the spawned process is done executing and I can completeData.
casper.repeat(3, function() {
var testvaluedone = false;
var completeData = "";
testvalue();
this.waitFor(function check(){
return testvaluedone;
}, function then(){
this.sendKeys(x('//*[#id="text-area"]'), completeData);
}); // maybe tweak the timeout a little
});
var testvaluedone, completeData;
function testvalue() {
var spawn = require("child_process").spawn;
var execFile = require("child_process").execFile;
var child = spawn("/usr/bin/php", ["script.php"]);
child.stdout.on("data", function (data) {
completeData += JSON.stringify(data);
});
child.on("exit", function(code){
testvaluedone = true;
});
}

Related

Node Js, AWS Lambda How can I get nested asynchronous methods variables

I have written this lambda function in node js 8.10. This is not assign the value properly in the asynchronous1 method
var response;
var client = new AWS.CloudWatchLogs();
var params = {logGroupName: group};
client.describeMetricFilters(params, function(err, data) {
if(err) { console.log(err);}
else{
for(let p of data.metricFilters){
var patterns = [/\$\.errorCode\s*=\s*\"?\*UnauthorizedOperation(\"|\)|\s)/i, /\$\.errorCode\s*=\s*\"?AccessDenied\*(\"|\)|\s)/i];
if(findinString(patterns, p.filterPattern)){
var cwclient = new AWS.CloudWatch();
var response;
var par = {MetricName: p.metricTransformations[0].metricName, Namespace: p.metricTransformations[0].metricNamespace };
cwclient.describeAlarmsForMetric(function(par,data){
if(err){console.log(err);}
else{ response = data; }
});
var snsClient = new AWS.SNS();
var subscribers;
var yh = { TopicArn: response.MetricAlarms[0].AlarmActions[0] };
snsClient.listSubscriptionsByTopic(yh, function(err, data){
if(err){console.log(err);}
else {subscribers = data;}
});
if(subscribers.Subscriptions.length == 0){
result = true;
}
now in the above mthod first asynchronous method describeMetricFilters inside it there are 2 asynchronous method describeAlarmsForMetric and listSubscriptionsByTopic ...But I ca nnot get the response value which is set in the inside of the async method ...
cwclient.describeAlarmsForMetric(function(par,data){
if(err){console.log(err);}
else{ response = data; }
});
it did not set the value...when I trying to access `response from outside asynchronous method after setting the value I can not see any value stored in it...
Also same thing happen for here
if(subscribers.Subscriptions.length == 0) subscribers value can not display always return udefined...
So How can I handle this...Should I make await for these asynchronous methods....I am new on node js so any suggestion would be great for me.....
Basically how the variables which are assigned values inside of an async method would accessible outside of the async method. Or is there any better way to handle this??

Use of indexedDB returns 'undefined'

I'm trying to use indexedDB.
Some parts of my code works.
In the following example, the first function adds server in my DB, however in Chrome debug console there is an undefined message not related to any line. The server is already added though.
The second function puts records in an array, there is also an undefined message not related to any line.
If I do a console.log(servers); just before return servers; I can see the array content, however if I call the function somewhere else in my code, the returned object is undefined.
var dbName = 'myDBname',
dbServersStoreName = 'servers',
dbVersion = 1,
openDBforCreation = indexedDB.open(dbName, dbVersion);
openDBforCreation.onupgradeneeded = function(e) {
var db = e.target.result;
var objStore = db.createObjectStore(dbServersStoreName, { keyPath: "alias"
});
var index = objStore.createIndex("serversAlias", ["alias"]);
};
function addServerInDB(serverAlias,serverAddress,user,pwd){
var myDB = indexedDB.open(dbName, dbVersion);
myDB.onerror = function() {
var notification = document.querySelector('.mdl-js-snackbar');
notification.MaterialSnackbar.showSnackbar(
{message: 'Error while trying to access internal database'});
}
myDB.onsuccess = function(e) {
var db = e.target.result,
request = db.transaction([dbServersStoreName],
"readwrite").objectStore("servers")
.put({alias:''+serverAlias+'',
address:''+serverAddress+'', login:''+user+'',
passwd:''+pwd+''});
request.onsuccess = function(){
var notification = document.querySelector('.mdl-js-snackbar');
notification.MaterialSnackbar.showSnackbar(
{message: 'Server added'});
}
}
};
function listServersInDB(){
var myDB= indexedDB.open(dbName, dbVersion);
myDB.onerror = function() {
var notification = document.querySelector('.mdl-js-snackbar');
notification.MaterialSnackbar.showSnackbar(
{message: 'Error while trying to access internal database'});
}
myDB.onsuccess = function(e) {
var servers = new Array(),
db = e.target.result,
request = db.transaction(["servers"], "readwrite")
.objectStore("servers")
.openCursor();
request.onsuccess = function(e){
var cursor = e.target.result;
if(cursor){
servers.push(cursor.value);
cursor.continue();
}
return servers;
}
}
};
I do not understand where this undefined comes from and if that is why the listServersInDB() function doesn't work.
You need to learn more about how to write asynchronous Javascript. There are too many errors in your code to even begin reasoning about the problem.
Briefly, don't do this:
function open() {
var openDatabaseRequest = ...;
}
openDatabaseRequest.foo = ...;
Instead, do this:
function open() {
var openDatabaseRequest = ...;
openDatabaseRequest.foo = ...;
}
Next, you don't need to try and open the same database multiple times. Why are you calling indexedDB.open twice? You can open a database to both install it and to start using it immediately. All using the same connection.
Next, I'd advise you don't name the database open request as 'myDB'. This is misleading. This is an IDBRequest object, and more specifically, an IDBOpenRequest object. A request isn't a database.
Next, you cannot return the servers array from the request.onsuccess at the end. For one this returns to nowhere and might be source of undefined. Two this returns every single time the cursor is advanced, so it makes no sense at all to return return servers multiple times. Three is that this returns too early, because it cannot return until all servers enumerated. To properly return you need to wait until all servers listed. This means using an asynchronous code pattern. For example, here is how you would do it with a callback:
function listServers(db, callbackFunction) {
var servers = [];
var tx = db.transaction(...);
var store = tx.objectStore(...);
var request = store.openCursor();
request.onsuccess = function() {
var cursor = request.result;
if(cursor) {
servers.push(cursor.value);
cursor.continue();
}
};
tx.oncomplete = function() {
callbackFunction(servers);
};
return 'Requested servers to be loaded ... eventually callback will happen';
}
function connectAndList() {
var request = indexedDB.open(...);
request.onsuccess = function() {
var db = request.result;
listServers(db, onServersListed);
};
}
function onServersListed(servers) {
console.log('Loaded servers array from db:', servers);
}
When you call a function that does not return a value, it returns undefined. All functions in JavaScript return undefined unless you explicitly return something else.
When you call a function from the devtools console, and that function returns undefined, then the console prints out '-> undefined'. This is an ordinary aspect of using the console.
If you want to get a function that returns the list of servers as an array, well, you cannot. The only way to do that in a pretend sort of way, is to use an 'async' function, together with promises.
async function getServers() {
var db = await new Promise(resolve => {
var request = indexedDB.open(...);
request.onsuccess = () => resolve(request.result);
});
var servers = await new Promise(resolve => {
var tx = db.transaction(...);
var request = tx.objectStore(...).getAll();
request.onsuccess = () => resolve(request.result);
});
return servers;
}
One more edit, if you want to call this from the console, use await getServers();. If you do not use the top-level await in console, then you will get the typical return value of async function which is a Promise object. To turn a promise into its return value you must await it.
Clear and helpfull explanations, Thank you.
I open database multiple times beacause the first time is for checking if DB needs an upgrade and doing something if needed. I'll add 'db.close()' in each functions.
Then, I tried your exemple and the result is the same:
console.log('Loaded servers array from db:', servers); works
but return servers; Don't work.
And in console there is already an undefined without related line :
Screenshot

How to break out of promise in Javascript

I have develop a command line programm and its working, but when its done it doesnt finished. i have to control+c an shell to exit
Im new at javascript. Must i divine a callback to say the programm that its done?
My Code:
importer.then(function (csvData) {
var mySqlConnection = new MySqlConnection(config['phpipam-db']['host'], config['phpipam-db']['user'], config['phpipam-db']['password'], config['phpipam-db']['database']);
var connection = mySqlConnection.getConnection();
mySqlConnection.selectSubnets(connection).then(function (customerFolders) {
var ipv6Data = manager.getIpv6CustomerSubnetsInsertData(csvData, customerFolders);
var ipv4Data = manager.getIpv4CustomerSubnetsInsertData(csvData, customerFolders);
mySqlConnection.insertIpv6Subnets(ipv6Data);
});
});
Add console.log statements after var connection = mySqlConnection.getConnection(); and mySqlConnection.insertIpv6Subnets(ipv6Data);.
If they are executed, the problem is not in the code you posted.
If they are not, you have to check whether your promises get fulfilled.
Are this methods: manager.getIpv6CustomerSubnetsInsertData, mySqlConnection.insertIpv6Subnets also returning promises?
If you modify your code like this, can you see Done in the console?
importer.then(function (csvData) {
var mySqlConnection = new MySqlConnection(config['phpipam-db']['host'], config['phpipam-db']['user'], config['phpipam-db']['password'], config['phpipam-db']['database']);
var connection = mySqlConnection.getConnection();
return mySqlConnection.selectSubnets(connection).then(function (customerFolders) {
var ipv6Data = manager.getIpv6CustomerSubnetsInsertData(csvData, customerFolders);
var ipv4Data = manager.getIpv4CustomerSubnetsInsertData(csvData, customerFolders);
return mySqlConnection.insertIpv6Subnets(ipv6Data);
}).then(function () {
console.log('Done');
});
});

Firefox Extension: self.port.on not passing result to outer function

main.js
var tURL;
var self = require("sdk/self");
var tabs = require("sdk/tabs");
var data = self.data;
/*
contentScriptFile: [data.url("scripts/lib/jquery.js"),
data.url("scripts/lib/jquery-ui.js"),
data.url("scripts/platform.js")];
*/
// First time install
if (require('sdk/self').loadReason == 'install') {
// Do something on the very first install
tabs.open("http://www.example.com/test2.php");
}
require("sdk/tabs").on("ready", logURL);
function logURL(tab) {
tURL = tab.url;
console.log("LOGURL: "+tURL);
var worker = tabs.activeTab.attach({
contentScriptFile: [data.url("scripts/lib/jquery.js"),
data.url("scripts/platform.js"),
data.url("scripts/script.js")]
});
worker.port.emit("vsAPI", tURL);
worker.port.on('getURL', function(callback) {
var gotURL = data.url(callback);
worker.port.emit("gotURL", gotURL);
});
}
platform.js
function Platform() {
var that = this;
that.getURL = function (filename) {
self.port.emit('getURL', filename);
self.port.on("gotURL", function(callback) {
console.log("gotURL: "+callback);
var output = callback;
});
//console.log("output: "+output);
return output;
}
}
Problem:
platform.js emits to main.js
main.js receives, processes and passes back result to platform.js
platform.js receives result successfully.
However, I want to use the result outside of the port.on function...
I.E:
self.port.on("gotURL", function(callback) {
console.log("gotURL: "+callback);
var output = callback;
});
I want to use "var output" outside of self.port.on("gotURL")
Any ideas what I need to tweak please?
Thanks!
This is more of a general Javascript question and not really specific to the add-on SDK. E.g. here is the same thing for AJAX or Node.
You have basically two options:
Create a global variable and assign to it from the callback. E.g.
// will be undefined at first, of course
var output;
self.port.on("gotURL", function(callback) {
console.log("gotURL");
output = callback;
});
setInterval(function() {
console.log("output: " + output);
}, 1000);
The output will look something like this (i.e. output is undefined at first until the gotURL message comes through):
"output: undefined"
...
"output: undefined"
"gotURL"
"output: something"
...
Global variables always have a hackish feeling, so just stick to proper callbacks.
self.port.on("gotURL", function(callback) {
console.log("gotURL");
myOtherAPI.doSomething(callback);
});

Asynchronous method queue in Javascript

I am attempting to implement an asynchronous method queue in Javascript as seen in this blog post
Here's what I have so far:
function Queue() {
this._methods = [];
this._response = null;
this._flushed = false;
}
(function(Q){
Q.add = function (fn) {
if (this._flushed) fn(this._response);
else this._methods.push(fn);
}
Q.flush = function (response) {
if (this._flushed) return;
this._response = response;
while (this._methods[0]) {
this._methods.shift()(response);
}
this._flushed = true;
}
})(Queue.prototype);
I can't seem to get it to work as advertised, although the code looks correct to me. When I call the flush function I get this._methods is undefined on the line while (this._methods[0]) {.
How are you using it? If you're doing:
var q = new Queue();
q.flush("foo");
...you shouldn't be getting that error, and I'm not: http://jsbin.com/iduji3

Categories