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');
});
});
Related
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
The following code seems to be behaving strangely. Basically, I'm importing a list of line-separated sentences from a text file, then making an array out of them. But when I try to choose a random sentence from the array, it doesn't work because sentenceString becomes undefined.
However, when I run
Math.floor(Math.random() * (sentenceArr.length) + 1);
I get a nice random number as expected.
And when I run sentenceArr.length
I get the number 12, which is indeed the length.
What am I missing?
var sentenceArr = [];
$.get('sentences.txt', function(data){
sentenceArr = data.split('\n');
});
var rand = Math.floor(Math.random() * (sentenceArr.length) + 1);
var sentenceString = sentenceArr[rand];
var sentence = sentenceString.split(' ');
Update:
I tried making a Promise as suggested below, but it still doesn't seem to be working. My new code with the Promise looks like this:
var sentenceArr = [];
var done = false;
function loadSentences() {
var rand = Math.floor(Math.random() * (sentenceArr.length) + 1);
var sentenceString = sentenceArr[rand];
var sentence = sentenceString.split(' ');
};
$.get('/sentences.txt', function(data){
sentenceArr = data.split('\n');
done = true;
});
var isItDone = new Promise(function(resolve) {
if(done) {
resolve('it worked');
}
});
//consume the promise:
var checkIfDone = function() {
isItDone
.then(function (fulfilled) {
loadSentences();
})
.catch(function (error) {
console.log('oops, it failed');
});
};
checkIfDone();
This seems to always return "oops, it failed", as if the promise is never fulfilled. However, when I check the value of "done", it is "true", meaning the Ajax request was completed before moving on to the next steps. Could anyone enlighten me? I've read three tutorials on promises already, and can't seem to figure out my error in applying the concept to my own code. Thank you.
The problem is you are trying to manipulate the file content before the response of server be complete.
Take a look at promises to understand more https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
And the way to solve your question using jquery ajax api.
var sentenceArr = [];
var file = 'path/to/file';
$.get(file)
.done(function (data) {
sentenceArr = data.split('\n');
var rand = Math.floor(Math.random() * (sentenceArr.length) + 1);
var sentenceString = sentenceArr[rand];
var sentence = sentenceString.split(' ');
console.log(sentenceArr)
console.log(rand)
console.log(sentenceString)
console.log(sentence)
});
Thanks, I solved the issue by first wrapping everything in a function, and using .then() to run everything only after the Ajax "get" was completed:
var sentenceArr = [];
const getData = () =>
$.get('http://eslquiz.net/wordmix/sentences.txt', function(data){
})
.then(data => { // use this format to run function only after json get is done (since it's async)
// "data" is the contents of the text file
sentenceArr = data.split('\n');
console.log('Made sentence array');
loadSentences();
});
I am writing some JavaScript codes using Parse.com.
To be honest, I have been reading how to use Promise and done lots of research but cannot still figure out how to use it properly..
Here is a scenario:
I have two tables (objects) called Client and InvoiceHeader
Client can have multiple InvoiceHeaders.
InvoiceHeader has a column called "Amount" and I want a total amount of each client's InvoiceHeaders.
For example, if Client A has two InvoiceHeaders with amount 30 and 20 and Client B has got nothing, the result I want to see in tempArray is '50, 0'.
However, with the following codes, it looks like it's random. I mean sometimes the tempArray got '50, 50' or "50, 0". I suspect it is due to the wrong usage of Promise.
Please help me. I have been looking into the codes and stuck for a few days.
$(document).ready(function() {
var client = Parse.Object.extend("Client");
var query = new Parse.Query(client);
var tempArray = [];
query.find().then(function(objects) {
return objects;
}).then(function (objects) {
var promises = [];
var totalForHeader = 0;
objects.forEach(function(object) {
totalForHeader = 0;
var invoiceHeader = Parse.Object.extend('InvoiceHeader');
var queryForInvoiceHeader = new Parse.Query(invoiceHeader);
queryForInvoiceHeader.equalTo('headerClient', object);
var prom = queryForInvoiceHeader.find().then(function(headers) {
headers.forEach(function(header) {
totalForHeader += totalForHeader +
parseFloat(header.get('headerOutstandingAmount'));
});
tempArray.push(totalForHeader);
});
promises.push(prom);
});
return Parse.Promise.when.apply(Parse.Promise, promises);
}).then(function () {
// after all of above jobs are done, do something here...
});
} );
Assuming Parse.com's Promise class follows the A+ spec, and I understood which bits you wanted to end up where, this ought to work:
$(document).ready(function() {
var clientClass = Parse.Object.extend("Client");
var clientQuery = new Parse.Query(clientClass);
clientQuery.find().then(function(clients) {
var totalPromises = [];
clients.forEach(function(client) {
var invoiceHeaderClass = Parse.Object.extend('InvoiceHeader');
var invoiceHeaderQuery = new Parse.Query(invoiceHeaderClass);
invoiceHeaderQuery.equalTo('headerClient', client);
var totalPromise = invoiceHeaderQuery.find().then(function(invoiceHeaders) {
var totalForHeader = 0;
invoiceHeaders.forEach(function(invoiceHeader) {
totalForHeader += parseFloat(invoiceHeader.get('headerOutstandingAmount'));
});
return totalForHeader;
});
totalPromises.push(totalPromise);
});
return Parse.Promise.when(totalPromises);
}).then(function(totals) {
// here you can use the `totals` array.
});
});
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;
});
}
I have a similar question here, but I thought I'd ask it a different way to cast a wider net. I haven't come across a workable solution yet (that I know of).
I'd like for XCode to issue a JavaScript command and get a return value back from an executeSql callback.
From the research that I've been reading, I can't issue a synchronous executeSql command. The closest I came was trying to Spin Lock until I got the callback. But that hasn't worked yet either. Maybe my spinning isn't giving the callback chance to come back (See code below).
Q: How can jQuery have an async=false argument when it comes to Ajax? Is there something different about XHR than there is about the executeSql command?
Here is my proof-of-concept so far: (Please don't laugh)
// First define any dom elements that are referenced more than once.
var dom = {};
dom.TestID = $('#TestID'); // <input id="TestID">
dom.msg = $('#msg'); // <div id="msg"></div>
window.dbo = openDatabase('POC','1.0','Proof-Of-Concept', 1024*1024); // 1MB
!function($, window, undefined) {
var Variables = {}; // Variables that are to be passed from one function to another.
Variables.Ready = new $.Deferred();
Variables.DropTableDeferred = new $.Deferred();
Variables.CreateTableDeferred = new $.Deferred();
window.dbo.transaction(function(myTrans) {
myTrans.executeSql(
'drop table Test;',
[],
Variables.DropTableDeferred.resolve()
// ,WebSqlError
);
});
$.when(Variables.DropTableDeferred).done(function() {
window.dbo.transaction(function(myTrans) {
myTrans.executeSql(
'CREATE TABLE IF NOT EXISTS Test'
+ '(TestID Integer NOT NULL PRIMARY KEY'
+ ',TestSort Int'
+ ');',
[],
Variables.CreateTableDeferred.resolve(),
WebSqlError
);
});
});
$.when(Variables.CreateTableDeferred).done(function() {
for (var i=0;i < 10;i++) {
myFunction(i);
};
Variables.Ready.resolve();
function myFunction(i) {
window.dbo.transaction(function(myTrans) {
myTrans.executeSql(
'INSERT INTO Test(TestID,TestSort) VALUES(?,?)',
[
i
,i+100000
]
,function() {}
,WebSqlError
)
});
};
});
$.when(Variables.Ready).done(function() {
$('#Save').removeAttr('disabled');
});
}(jQuery, window);
!function($, window, undefined) {
var Variables = {};
$(document).on('click','#Save',function() {
var local = {};
local.result = barcode.Scan(dom.TestID.val());
console.log(local.result);
});
var mySuccess = function(transaction, argument) {
var local = {};
for (local.i=0; local.i < argument.rows.length; local.i++) {
local.qry = argument.rows.item(local.i);
Variables.result = local.qry.TestSort;
}
Variables.Return = true;
};
var myError = function(transaction, argument) {
dom.msg.text(argument.message);
Variables.result = '';
Variables.Return = true;
}
var barcode = {};
barcode.Scan = function(argument) {
var local = {};
Variables.result = '';
Variables.Return = false;
window.dbo.transaction(function(myTrans) {
myTrans.executeSql(
'SELECT * FROM Test WHERE TestID=?'
,[argument]
,mySuccess
,myError
)
});
for (local.I = 0;local.I < 3; local.I++) { // Try a bunch of times.
if (Variables.Return) break; // Gets set in mySuccess and myError
SpinLock(250);
}
return Variables.result;
}
var SpinLock = function(milliseconds) {
var local = {};
local.StartTime = Date.now();
do {
} while (Date.now() < local.StartTime + milliseconds);
}
function WebSqlError(tx,result) {
if (dom.msg.text()) {
dom.msg.append('<br>');
}
dom.msg.append(result.message);
}
}(jQuery, window);
Is there something different about XHR than there is about the executeSql command?
Kind of.
How can jQuery have an async=false argument when it comes to Ajax?
Ajax, or rather XMLHttpRequest, isn't strictly limited to being asynchronous -- though, as the original acronym suggested, it is preferred.
jQuery.ajax()'s async option is tied to the boolean async argument of xhr.open():
void open(
DOMString method,
DOMString url,
optional boolean async, // <---
optional DOMString user,
optional DOMString password
);
The Web SQL Database spec does also define a Synchronous database API. However, it's only available to implementations of the WorkerUtils interface, defined primarily for Web Workers:
window.dbo = openDatabaseSync('POC','1.0','Proof-Of-Concept', 1024*1024);
var results;
window.dbo.transaction(function (trans) {
results = trans.executeSql('...');
});
If the environment running the script hasn't implemented this interface, then you're stuck with the asynchronous API and returning the result will not be feasible. You can't force blocking/waiting of asynchronous tasks for the reason you suspected:
Maybe my spinning isn't giving the callback chance to come back (See code below).