Trouble using Breeze offline data getting undefined is not a function - javascript

Am having trouble using offline data with breeze, Most functions work fine while online.
Then an error undefined is not a function arise in the function i guess when calling this fuction
$scope.getPagedDataAsync = function (pageSize, page, searchText) {
var skip = (page - 1) * pageSize;
var take = pageSize * 1;
app.dataservice.getCustomerPage(skip, take, searchText)
.then(customersQuerySucceeded);
};
Here is the modified getCustomerPage function to work offline
function getCustomerPage(skip, take, searchText) {
var importData = window.localStorage.getItem(stashAll);
manager2.importEntities(importData);
var query = breeze.EntityQuery
.from("Customers")
.orderBy("CompanyName")
.skip(skip).take(take)
.inlineCount(true);
if (searchText) {
query = query.where("CompanyName", "contains", searchText);
}
return manager2.executeQueryLocally(query);
}
And Here is how i declared manager2 for offline usage
var manager2 = new breeze.EntityManager();
And here is customersQuerySucceeded function where i think error arise, i works fine while online on the samples.
function customersQuerySucceeded(data) {
$scope.offlinecustomers = data.results;
if (data.inlineCount) {
$scope.totalServerItems = data.inlineCount;
}
$scope.$apply();
app.logger.info("Fetched " + data.results.length + " Offline Customers ");
}
Here is how i got data offline on the first place.
manager = new breeze.EntityManager(serviceName);
var query=breeze.EntityQuery
.from("Customers");
manager.executeQuery(query);
var exportData = manager.exportEntities();
window.localStorage.setItem(stashAll, exportData);

It turns out executeQueryLocally returns an data while executeQuery returns a promise,
The error was because i was referring to properties on a promise.
I guess i have to rewrite my code to account that...

Related

Undefined errors using Node.js, Mongoose, and Discord.js [Cannot read property of undefined]

I've been scouring similar problems but haven't seem to have found a solution that quite works on my end. So I'm working on a Discord bot that takes data from a MongoDB database and displays said data in the form of a discord embedded message using Mongoose. For the most part, everything is working fine, however one little section of my code is giving me trouble.
So I need to import an array of both all available users and the "time" data of each of those users. Here is the block of code I use to import said data:
for (i = 0;i < totalObj; i++){
timeArray[i] = await getData('time', i);
userArray[i] = await getData('user', i);
}
Now this for loop references a function I made called getData which obtains the data from MongoDB by this method:
async function getData(field, value){
var data;
await stats.find({}, function(err, result){
if(err){
result.send(err);
}else{
data = result[value];
}
});
if(field == "user"){
return data.user;
}else if (field == "time"){
return data.time;
}else{
return 0;
}
So that for loop is where my errors currently lie. When I try to run this code and display my data through a discord message, I get this error and the message does not get sent:
(node:13936) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'time' of undefined
Now the strange thing is, this error does not happen every time. If I continue calling the command that triggers this code from my discord server, it's almost like a 50/50 shot if the command actually shows the message or instead gives this error. It is very inconsistent.
This error is confounding me, as the undefined part does not make sense to me. The objects that are being searched for in the mongoDB collection are definitely defined, and the for loop never exceeds the number of objects present. My only conclusion is that I'm doing something wrong with my asynchronous function design. I have tried altering code to use the getData function less often, or to not use awaits or asynchronous design at all, however this leaves my final discord message with several undefined variables and an eventual crash.
If anyone has any advice or suggestions, that would be very much appreciated. Just for reference, here is the full function that receives the data, sorts it, and prepares a string to be displayed on the discord server (though the error only seems to occur in the first for loop):
async function buildString(){
var string = "";
var totalObj;
var timeArray = [];
var userArray = [];
var stopSort = false;
await stats.find({}, function(err, result){
if(err){
result.send(err);
}else{
totalObj = result.length;
}
});
for (i = 0;i < totalObj; i++){
timeArray[i] = await getData('time', i);
userArray[i] = await getData('user', i);
}
while(!stopSort){
var keepSorting = false;
for(i = 0; i < totalObj ; i++){
var target = await convertTime(timeArray[i]);
for(j = i + 1 ; j < totalObj ; j++){
var comparison = await convertTime(timeArray[j]);
if(target > comparison){
//Switch target time with comparison time so that the lower time is up front
var temp = timeArray[i];
timeArray[i] = timeArray[j];
timeArray[j] = temp;
//Then switch the users around so that the user always corresponds with their time
var userTemp = userArray[i];
userArray[i] = userArray[j];
userArray[j] = userTemp;
//The loop will continue if even a single switch is made
keepSorting = true;
}
}
}
if(!keepSorting){
stopSort = true;
}
}
//String building starts here
var placeArray = [':first_place: **1st', ':second_place: **2nd', ':third_place: **3rd', '**4th', '**5th', '**6th', '**7th', '**8th', '**9th', '**10th'];
for(i = 0; i < totalObj; i++){
string = await string.concat(placeArray[i] + ": " + userArray[i] + "** - " + timeArray[i] + " \n\n");
console.log('butt');
}
console.log("This String:" + string);
return string;
}
I think problem is you are trying to await function with callback, it will not work => access to data.time may run before data = result[value]. If you need await callback, you can use custom Promise (or use util.promisify, more info here)
Promise:
function findStats(options) {
return new Promise((resolve, reject) => {
return stats.find(options, function (err, result) {
if (err) {
return reject(err)
}
return resolve(result)
})
})
}
utils.promisify
const util = require('util');
const findStats = util.promisify(stats.find);
Now you can use await in your function
async function getData(field, value) {
try {
const result = await findStats({})
const data = result.value
if (field === 'user') {
return data.user
}
if (field === 'time') {
return data.time
}
return 0
} catch (error) {
// here process error the way you like
// or remove try-catch block and sanitize error in your wrap function
}
}

Unable to update table in Advanced Data Persistence mode

I have an issue related to database. I am currently working with Gupshup bot programming. There are two different data persistence modes which can be read here and here. In the advanced data persistence, the following code is documented to put data into data base:
function MessageHandler(context, event) {
if(event.message=='update bug - 1452') {
jiraUpdate(context);
}
}
function jiraUpdate(context){
//connect to Jira and check for latest update and values
if(true){
context.simpledb.doPut("1452" ,"{\"status\":\"QA pending\",\"lastUpdated\":\"06\/05\/2016\",\"userName\":\"John\",\"comment\":\"Dependent on builds team to provide right build\"}");
} else{
context.sendResponse('No new updates');
}
}
function DbPutHandler(context, event) {
context.sendResponse("New update in the bug, type in the bug id to see the update");
}
If I want to change only one of column (say status or last Updated) in the table for the row with key value 1452, I am unable to do that. How can that be done?
I used the following code:
function MessageHandler(context, event) {
// var nlpToken = "xxxxxxxxxxxxxxxxxxxxxxx";//Your API.ai token
// context.sendResponse(JSON.stringify(event));
if(event.message=='deposit') {
context.sendResponse("Enter the amount to be deposited");
}
if(event.message=="1000") {
jiraUpdate(context);
}
if(event.message== "show"){
context.simpledb.doGet("1452");
}
}
function HttpResponseHandler(context, event) {
var dateJson = JSON.parse(event.getresp);
var date = dateJson.date;
context.sendResponse("Today's date is : "+date+":-)");
}
function jiraUpdate(context){
//connect to Jira and check for latest update and values
if(true){
context.simpledb.doPut("aaa" ,"{\"account_number\":\"90400\",\"balance\":\"5800\"}");
} else{
context.sendResponse('No new updates');
}
}
/** Functions declared below are required **/
function EventHandler(context, event) {
if (!context.simpledb.botleveldata.numinstance)
context.simpledb.botleveldata.numinstance = 0;
numinstances = parseInt(context.simpledb.botleveldata.numinstance) + 1;
context.simpledb.botleveldata.numinstance = numinstances;
context.sendResponse("Thanks for adding me. You are:" + numinstances);
}
function DbGetHandler(context, event) {
var bugObj = JSON.parse(event.dbval);
var bal = bugObj.balance;
var acc = bugObj.account_number;
context.sendResponse(bal);
var a = parseInt (bal,10);
var b = a +1000;
var num = b.toString();
context.simpledb.doPut.aaa.balance = num;
}
function DbPutHandler(context, event) {
context.sendResponse("testdbput keyword was last put by:" + event.dbval);
}
Since the hosted DB that is provided by Gupshup is the DynamoDB of AWS. Hence you can enter something as a key, value pair.
Hence you will have to set the right key while using doPut method to store data into the database and use the same key to get the data from the database using the doGet method.
To update the data you should first call doGet method and then update the JSON with right data and then call doPut method to update the database with the latest data.
I have also added something which is not present in the documentation, You can now make DB calls and choose which function the response goes to.
I am refactoring your example as using 3 keywords and hard coding few things just for example -
have - this will update the database with these values
{"account_number":"90400","balance":"5800"}
deposit - on this, the code will add 1000 to the balance
show - on this, the code show the balance to the user.
Code -
function MessageHandler(context, event) {
if(event.message=='have') {
var data = {"account_number":"90400","balance":"5800"};
context.simpledb.doPut(event.sender,JSON.stringify(data),insertData); //using event.sender to keep the key unique
return;
}
if(event.message=="deposit") {
context.simpledb.doGet(event.sender, updateData);
return;
}
if(event.message== "show"){
context.simpledb.doGet(event.sender);
return;
}
}
function insertData(context){
context.sendResponse("I have your data now. To update just say \"deposit\"");
}
function updateData(context,event){
var bugObj = JSON.parse(event.dbval);
var bal = bugObj.balance;
var a = parseInt(bal,10);
var b = a + 1000;
var num = b.toString();
bugObj.balance = num;
context.simpledb.doPut(event.sender,bugObj);
}
function EventHandler(context, event) {
if (!context.simpledb.botleveldata.numinstance)
context.simpledb.botleveldata.numinstance = 0;
numinstances = parseInt(context.simpledb.botleveldata.numinstance) + 1;
context.simpledb.botleveldata.numinstance = numinstances;
context.sendResponse("Thanks for adding me. You are:" + numinstances);
}
function DbGetHandler(context, event) {
var accountObj = JSON.parse(event.dbval);
context.sendResponse(accountObj);
}
function DbPutHandler(context, event) {
context.sendResponse("I have updated your data. Just say \"show\" to view the data.");
}

Return an object when the promise finishes inside a require

When i was writing this promise to query an sql datbase i was not testing it with require i was just running the js file straight from node in the console. Now i need it to return the data when finishing the loop and I can't figure out how. Promises as well as reading data from an SQL are both new to me so i was happy to have gotten it working. But now when i require this code with
var dbData = new getDataSQL();
it returns {} instead of a nice big chunk of data.
It finishes its promises but the data is not returned.
Any ideas on how best to return the data?
module.exports = function getDataSQL(){
//JSON OBJECTS
var dates = require('./JSON/dates.js');
var companies = require('./JSON/companies.js');
//SQL FUNCTION
var sqlConJS = require('./sqlCon.js');
function fn(retVal, i, startDate, endDate){
data[i] = JSON.parse(retVal);
var total = 0;
for(var b = 0; b<Object.keys(data[i].result).length;b++){
total = total + data[i].result[b].Amount
}
data[i].totalAmount = total;
data[i].startDate = startDate;
data[i].endDate = endDate;
console.log("No= "+i,"Reccs= " + Object.keys(data[i].result).length,"StartDate=" + startDate,"EndDate=" + endDate, "Amount = " + Math.floor(total));
dataP();
}
//INIT SQL QUERY
var data = [];
var incrDat = 0;
var dataPromise = function(i){
return new Promise(function(resolve, reject){
data[i]={};
var sqlCon = new sqlConJS(fn, dates[i].startDate, dates[i].endDate, companies[9].company, i);
if(dates.length===i)reject();
else resolve();
});
};
var dataP = function(){
dataPromise(incrDat++).then().catch(function(){
console.log("done!");
console.log(data[0].result[0]["Posting Date"]);
return data;
});
}
dataP();
}
Never mind i got it, callback function offcourse! I have so much to learn still. Add cbRetData when declaring the function at the top.
module.exports = function getDataSQL(cbRetData){
under Console.log("done!"); i put
cbRetData(data);
in the main js script we create the function cbRetData like so
function cbRetData(retData){
dbData = retData;
console.log("retData to dbData coming in!");
console.log(dbData);
}
where we call the getDataSQL function after requiring it u simply pass the function cbRetData along like so.
var getdbData = new getDataSQL(cbRetData);
I'm only just beginning to come to terms with callback functions and such.

How To handle result set of websql in html 5?

I m creating mobile web application using html5 and javascript.I m having two javascript files. AttributesDatabase.js and AttributeView.js.From AttributeView.js i m calling one function from AttributeDatabase.js in that i m executing one select query.Now the query result should go to AtttributeView.js.But the Websql transaction is asynchronous call that is what it is not returning proper result.Is there any way to handle the websql result.
Please help if any way there?
Edited
AttributeView.js
var AttributeDAOObj = new AttributeDAO();
AttributeDAOObj.GetAttributeList();
alert(AttributeDAOObj.GetAttributeList()); //This alert is coming as undefined.
AttributeDAO.js
this.GetAttributeList = function () {
var baseDAOObj = new BaseDAO();
var query = "SELECT AttributeName FROM LOGS";
// this.Successcalbackfromsrc = this.myInstance.Successcalback;
var parm = { 'query': query, 'Successcalback': this.myInstance.Successcalback };
baseDAOObj.executeSql(parm);
}
//To Create database and execute sql queries.
function BaseDAO() {
this.myInstance = this;
//Creating database
this.GetMobileWebDB = function () {
if (dbName == null) {
var dbName = 'ABC';
}
var objMobileWebDB = window.openDatabase(dbName, "1.0", dbName, 5 * 1024 * 1024);
return objMobileWebDB;
}
//Executing queries and getting result
this.executeSql = function (query) {
var objMobileWebDB = this.myInstance.GetMobileWebDB();
objMobileWebDB.transaction(function (transaction) {
//In this transaction i m returning the result.The result value is coming.
transaction.executeSql(query, [], function (transaction, result) { return result; }, this.Errorclback);
});
}
}
The problem is in you succes call back (like in the comment to your question, stated by DCoder)
function (transaction, result) { return result; }
this is returning where to?
So this is how to do it (or at least one way)
you can do for example:
function (transaction,result){
console.log("yes, I have some result, but this doesn't say anything, empty result gives also a result");
// so check if there is a result:
if (result != null && result.rows != null) {
if (result.rows.length == 0) {
// do something if there is no result
}else{
for ( var i = 0; i < result.rows.length; i++) {
var row = result.rows.item(i);
var id = result.rows.item(i).id; //supposing there is an id in your result
console.log('Yeah! row id = '+id);
}
}
}else{
// do something if there is no result
}
};
note the code above can be compacter, but this is how to understand it better.
another way is to put this function is a seperate piece of code, so you keep the sql statement more compact and readable. Like you call you error callback this can be in your function (with this. in front of it) or a completely seperate function.

How does jQuery do async:false in its $.ajax method?

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

Categories