get return value from sql request - javascript

I'm currently working on a little app using phonegap and sqllite.
Filling the database works fine; but I need a function which returns me a html-string (for a id).
I have this little snippet from the internet which I "improved" for my purpose, but it doesn't work like expected :(
function getPriceFromDatabase(id) {
var result = [];
// Query the database
//
function queryDB(tx) {
tx.executeSql('SELECT * FROM PRICEFTS WHERE pid MATCH ' + id, [], querySuccess, errorCB1);
}
// Query the success callback
//
function querySuccess(tx, results) {
var len = results.rows.length;
for (var i = 0; i < len; i++) {
result.push('<span class="'+results.rows.item(i).priceart+'">'+results.rows.item(i).price+'</span>');
}
}
// Transaction error callback
//
function errorCB1(err) {
console.log("Error SQL: " + err.code);
}
// Transaction success callback
//
var db = window.openDatabase("sucheDB", "1.0", "Suche DB", 52428800);
db.transaction(queryDB, errorCB1);
return result.join('');
}
Here is my sample event:
$("#price_button").click(function () {
var p = getPriceFromDatabase(88361);
console.log(p);
$('#price').html(p);
})
(I get always 'undefined' as result)
can someone help?
thanks! :)

You should provide the on-success callback to the db.transaction call, like this:
db.transaction(queryDB, errorCB1, querySuccess);
Also this function is probably async, so your return is executed before the transaction could finish.

Related

Asynchronously get generated array on function and pass it out of the box [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
Problem resolved on Asynchronously solution to check data from database kinds of loop clause
with this below code i can generate simple array as jsonArray into checkUserMobileNumberAsEwallet function, but i can't pass it out of that to send inside client,
with socket.emit('syncContacts', accountNumbers) i get [] result on accountNumbers, but into if (success) { statement array successful created and pushed into accountNumbers array
socket.on('syncContacts', function (data) {
var accountNumbers = [];
for (var i = 0; i < data.length; i++) {
checkUserMobileNumberAsEwallet(data[i].mobileNumber, function (success) {
if (success) {
accountNumbers.push({ewalletNumber: this.mobileNumber});
console.log(accountNumbers);
}
}.bind({mobileNumber: data[i].mobileNumber}));
}
console.log(accountNumbers);
socket.emit('syncContacts', accountNumbers);
});
function checkUserMobileNumberAsEwallet(mobileNumber, callback) {
var mobileNumber = mobileNumber.substr(1, mobileNumber.length);
var query = "SELECT id FROM userEwallets WHERE ewalletNumber LIKE '%" + mobileNumber + "'";
connection.query(query, function (err, results) {
if (err) return callback(false);
if (results.length === 0)
return callback(false);
else {
return callback(true);
}
});
}
Updated after post comments:
socket.on('syncContacts', function (data) {
//console.log(accountNumbers);
//socket.emit('syncContacts', accountNumbers);
async.parallel(
[
function (callback) {
var accountNumbers = [];
for (var i = 0; i < data.length; i++) {
checkUserMobileNumberAsEwallet(data[i].mobileNumber, function (success) {
if (success) {
accountNumbers.push({ewalletNumber: this.mobileNumber});
console.log(accountNumbers);
}
}.bind({mobileNumber: data[i].mobileNumber}));
}
callback(success, accountNumbers);
}
],
function (success, results) {
console.log("results " + results.toString());
socket.emit('syncContacts', results);
});
});
function checkUserMobileNumberAsEwallet(mobileNumber, callback) {
var mobileNumber = mobileNumber.substr(1, mobileNumber.length);
var query = "SELECT id FROM userEwallets WHERE ewalletNumber LIKE '%" + mobileNumber + "'";
connection.query(query, function (err, results) {
if (err) return callback(false);
if (results.length === 0)
return callback(false);
else {
return callback(true);
}
});
}
Based on our code, it seems like checkUserMobileNumberAsEwallet is an asynchronous event, which accepts a function callback. That would mean that the for-loop would execute, which would queue up executions to checkUserMobileNumberAsEwallet. Immediately after the for-loop executes, console.log would correctly output the empty array accountNumbers and emit the event through the socket. Then the callback functions to each checkUserMobileNumberAsEwallet execution would begin to execute, and log the accountNumbers array which now has data.
This can be solved in a few ways, but likely the easiest and most readable would be to create Promises, and act on the Promises when they resolve. Personally I like the 'when' promise library, but many libraries could help to solve this problem. https://github.com/cujojs/when/blob/master/docs/api.md#whensettle
The problem is that you have no control over when the code inside the callback executes, and it ends up executing after you've already called socket.emit.
You can either a) use an async aggregator to call a callback for each successful mobile number and then, when all of those have finished, call the socket.emit call OR b) do something like what I did below. Alter your checkUserMobileNumberAsEwallet function to accept and verify an array of mobile numbers, and pass the successful numbers to your callback function
Try the following:
socket.on('syncContacts', function (data) {
var accountNumbers = [];
var mobileNumbers = [];
for (var i = 0; i < data.length; i++) {
mobileNumbers.push(data[i].mobileNumber);
}
checkUserMobileNumberAsEwallet(mobileNumbers, function (successfulNumbers) {
if (successfulNumbers.length > 0) {
for (var i = 0; i < successfulNumbers.length; i++) {
accountNumbers.push({ewalletNumber: successfulNumbers[i]});
}
socket.emit('syncContacts', accountNumbers);
}
}.bind({mobileNumbers: mobileNumbers}));
});

Return executeSQL function

I'm trying to return the results of a SQL query using SQLite.
The query works fine and I can output the results inside the executeSql function. But when I try to reach the array from my main function (returnSQLArray) it is undefined.
How do I solve this problem?
I'm calling returnSQLArray inside another function where I need the results from the query.
Code:
function returnSQLArray(str)
{
var db = window.openDatabase("Database", "1.0", "Name", 200000);
var result = [];
db.transaction(
function (tx, results) {
tx.executeSql(str, [], function(tx, rs) {
for(var i=0; i<rs.rows.length; i++) {
var row = rs.rows.item(i)
result[i] = {
id: row['id']
}
}
console.log(result[0].id); //Returns the id
});
}
);
console.log(result[0].id); //Undefined
}
Thank you
It's an async issue. db.transaction takes a callback which executes after the sqlite transaction finishes. Your console.log() statement shown at the end of your method is actually happening before result has been populated.
EDIT ADDITION:
functions getPersons() {
returnSQLArray('SELECT * FROM PERSONS', processPersonsResponse);
}
function returnSQLArray(str, callback) {
...
tx.executeSql(str, [], function(tx, rs) { callback(result); });
}
function processPersonsResponse(response) {
//do work with response
}

Web SQL transaction does not execute properly in javascript function

I have JavaScript function that returns array of selected values from my local database.
var dataBase = {
select : selectFunction
}
var db = openDatabase(..);
var data=[ ];
function selectFunction() {
db.transaction(function (t) {
t.executeSql("SELECT * FROM Table", [], function (t, results) {
for (i = 0; i < results.rows.length; i++) {
data.push(results.rows.item(i));
}
});
});
return data;//return "stackoverflow" //works fine
}
I want to do something like this
var getSelect = dataBase.select();
alert(getSelect);
If I return string like "stackoverflow", this will work fine
alert result: stackoverflow
But if I try to return the 'data', the function returns undefined
I noticed that db.transaction is executing after the return statement, and I don't know how to fix this.
When returning results from an asynchronous function, you must use a callback, as the function will return before the actual operation has completed. You can rewrite your function like so:
function selectFunction(callback) {
db.transaction(function (t) {
t.executeSql("SELECT * FROM Table", [], function (t, results) {
for (i = 0; i < results.rows.length; i++) {
data.push(results.rows.item(i));
}
callback(data);
});
});
}
And then call it, passing a callback:
dataBase.select(function(data){
var getSelect = data
alert(getSelect);
});

How to return this value?

I am building a mobile app using phonegap, jQuery and jQuery mobile. I want to use SqLite database in my app for storing some user information. (I can't use local storage i want to do search/sort operations on the data)
This is the code I am working on to get this done,
function getAccountInformation(){
var accounts = {};
db.transaction(function(transaction) {
transaction.executeSql('SELECT * FROM account;', [],
function(transaction, result) {
if (result != null && result.rows != null) {
for (var i = 0; i < result.rows.length; i++) {
var item={};
var row = result.rows.item(i);
for(var prop in row){
item[prop]=row[prop]
}
accounts[i]=item;
}
}
},errorHandler
);
},errorHandler,nullHandler);
console.log(JSON.stringify(accounts));
}
If I put this console.log(JSON.stringify(accounts)); after the end } of the for loop it shows proper output.
But if I put it where it is right now the {} is printed as an output.
How can I make getAccountInformation() function return that accounts object to my other function? Where I will use jQuery to render the output.
What I want to do is return this accounts object simply by wrting
return accounts;
Because the SqLite functions are asynchronous you cannot just return the value.
I would make the getAccountInformation receiving a callback as below:
function getAccountInformation(callbackfn)
{
db.transaction(function(transaction),
.....,
function (transaction, result)
{
if (result != null)
{
callbackfn(result);
}
});
}
In such way you will get your function called when the db request executed.
That depends on when the function is called. When it is called asynchronously (like an AJAX request) you're out of luck. In that case I suggest you read about jQuery deferreds.
A code snippet based on deferreds could look like this:
var deferred = new jQuery.Deferred();
var accounts = {};
deferred.done(function(data) {
// process your data here
});
db.transaction(function(transaction) {
transaction.executeSql('SELECT * FROM account;', [],
function(transaction, result) {
if (result != null && result.rows != null) {
for (var i = 0; i < result.rows.length; i++) {
var item={};
var row = result.rows.item(i);
for(var prop in row){
item[prop]=row[prop]
}
accounts[i]=item;
}
deferred.resolve(accounts); // let the "done" function get called
} else {
deferred.reject();
}
}, errorHandler
);
},errorHandler,nullHandler);
db.transaction and transaction.executeSql produce their results asynchronously through the use of callback functions. This means that your getAccountInformation function will return immediately and will not wait for the transaction to complete (as in a synchronous call).
It's probably easier to simply pass in a callback function as an argument of your getAccountInformation and run that function when the accounts array is populated. Therefore, change your function signature to getAccountInformation(callback) and replace the executeSql callback with:
function(transaction, result) {
if (result != null && result.rows != null) {
for (var i = 0; i < result.rows.length; i++) {
var item={};
var row = result.rows.item(i);
for(var prop in row){
item[prop]=row[prop]
}
accounts[i]=item;
}
callback(accounts); // Call callback function with populated accounts
}
}
You can then call this function with:
getAccountInformation(function(accounts) {
// Do something with the accounts
});
There are fancier ways such as jQuery Deferreds and Promises which makes working with asynchronous functions easier, but you still need to understand why this exists. By using asynchronous actions, your application stays responsive while waiting for results.

Capture value from nested function in JavaScript

I have the following code snippet :
function getCheckListTaskWithId(id){
var tempTask = db.readTransaction(function (tx) {
tx.executeSql('SELECT * FROM checklisttasks where id=? ', [id], function (tx, results) {
var len = results.rows.length;
if(len>0){
var task=results.rows.item(0);
var temp= new CheckListTask(task.id,task.crud,task.name,task.status);
alert(temp);
}
});
});
}
the function that I pass to the tx.execute method is a call back function. Now I wan to return temp var present in callback function, from getCheckListTaskWithId function.
How Do I do this?
I am assuming that the executions of db.readTransaction and tx.executeSql are asynchronous. So you cannot return the result from them, as you don't know when they'll finish. The solution is use an asynchronous callback yourself. Make the getCheckListTaskWithId take a callback function as an argument and call it when result it available.
function getCheckListTaskWithId(id, callback) {
var tempTask = db.readTransaction(function (tx) {
tx.executeSql('SELECT * FROM checklisttasks where id=? ', [id], function (tx, results) {
var len = results.rows.length;
if(len > 0) {
var task=results.rows.item(0);
var temp= new CheckListTask(task.id,task.crud,task.name,task.status);
alert(temp);
callback(temp);
}
});
});
}
Rewrite tx.executeSql so it gets the return value of the callback and returns it.
This assumes that tx.executeSql doesn't perform any Ajax. Ajax is Asynchronous, so an HTTP request is made, execution continues as normal and another function is run when the request comes back. In this case it is far too late to return a value to the earlier function and anything that needs to be done with the data can only be done by the callback.

Categories

Resources