Incrementing Value of incoming value in Azure Table Insert - ios

I am an iOS developer & currently working with Azure mobile services SDK in iOS.
In my case, I am providing each user as a uniqueid say 'myid' in Table say 'todomytable'. In todomytable.js file I am performing check for myid value. If coming value of 'myid' from device is less than stored value in table then I am increasing incoming value greater than earlier stored value in table by One. Below is my logic in todomytable.js
table.insert(function (context) {
context.item.userId = context.user.id;
//....
var intIncomingID = context.item.myid; //ID coming from mobile device
//Call back to get max value of 'myid' from Table
var myFunction = function( callback) {
var query = {
sql: 'select MAX(myid) from TodoItem'
};
context.data.execute(query).then(function (results) {
var objectTest = eval(JSON.stringify(results));
var tempObject = objectTest[0];
var previuosIntID = tempObject["MAX(myid)"];
callback(previuosIntID);
});
};
myFunction(function(returnValue) {
console.log("returnValue is : "+returnValue);
if (intIncomingID<=returnValue)
{
console.log('IF');
context.item.userId = context.user.id;
returnValue = returnValue+1;
context.item.myid = returnValue;
console.log("UPDATED value is : "+context.item.myid);
}
else{
context.item.myid = intIncomingID;
console.log("ITEM value is :"+intIncomingID);
}
return context.execute();
});
});
But issue is that table is not getting update & in mobile log I am getting network request time out error as below
{Error Domain=NSURLErrorDomain Code=-1001 "The request timed out."}
Can anyone suggest how to resolve this issue? I have to store 'myid' in incremented order in table. I am new to Node.js, so sorry If I am making any foolish mistake.

It is likely that there is an exception occurring at some point that causes a promise to reject. Given that there is no promise exception handler defined, the exception ends up being "swallowed". Try the following:
var table = module.exports = require('azure-mobile-apps').table()
table.insert(function (context) {
context.item.userId = context.user.id;
var intIncomingID = context.item.myid; //ID coming from mobile device
var query = { sql: 'select MAX(myid) from TodoItem' };
return context.data.execute(query)
.then(function (results) {
var tempObject = results[0];
var previousIntID = tempObject["MAX(myid)"];
console.log("previous ID is : " + previousIntID);
if (intIncomingID <= previousIntID) {
context.item.myid = previousIntID + 1;
console.log("UPDATED value is : " + context.item.myid);
} else {
context.item.myid = intIncomingID;
console.log("ITEM value is :" + intIncomingID);
}
return context.execute();
});
});
Some points to note:
context.data.execute returns a promise - we are returning this from the insert function so that the Mobile Apps runtime handles any rejected promises
context.execute also returns a promise; we are returning this so that the promises are "chained" properly
Hope this helps!

Related

Autodesk Forge - out of memory with getBulkProperties

i made an forge viewer dashboard that shows different data from the viewer ( most of it is being analized in the client side)
when i open a large model, the viewer loads the model, but the graphs charts and buttons won't apear, and i get this error message:
Uncaught DOMException: Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope': Data cannot be cloned, out of memory.
what can i do to overcome this bug?
i am running the app on localhost3000. would deployment by microsoft azure help ?
is there a way to decrease the memory usage when the data calculation is being made?
this is where i call the proccessing functions after the model is being loaded:
function onGeometryLoaded() {
console.log("Geometry Loaded");
viewer.search(
"",
function (dbIds,propertyNames) {
viewer.model.getBulkProperties(
dbIds,
{propFilter:["Category","System Classification","Area","Reference Level",'System Type','Level','Type Name','Size','Length','Revit Walls','Base Constraint','Comments']},
// {propFilter:["Category","System Classification","Area","Reference Level",'System Type','Level','Type Name','Size','Revit Walls','Base Constraint','Comments']},
function (elements) {
// elements=elements.splice(1,elements.length/2);
// var levelName = setLevelDropDown(elements);//-->the first time- get the first level name
var levelNames = FindLevelNames(elements);//-->the first time- get the first level name
var property = "AF_Flow";
var flowCoefficient=1;
getListCategories(elements, function (cateElem) {
arraySimplify(elements,levelNames[0],property,flowCoefficient,cateElem, function (object) {
modData.quantities = object.quantities;
modData.Elements = object.Elements;
modData.elem = object.Elements.ele;
modData["Load"] = "Done";
// console.log(propNames);
// showPowerBIReport(levelNames,propNames);
console.log("Big calculation done");
showPowerBIReport(levelNames);
});
});
}
);
},
null,
["Comments"]
);
DashBoardColors = generateColorsRandom();
}
function onDocumentLoadFailure(viewerErrorCode, viewerErrorMsg) {
console.error('onDocumentLoadFailure() - errorCode:' + viewerErrorCode + '\n- errorMessage:' + viewerErrorMsg);
}
}
thanks!

SAPUI5 oData.V2 How to invoke a function after everything in a batch request is done?

I have an issue while making an SAPUI5 odata V2 batch request :
var that = this;
var oServiceModel = that.getModel("oServiceModel");
odataMod = this.getModel("Service");
odataMod.setUseBatch(true);
var aData = oServiceModel.getData();
var stupidService = _.filter(aData, function (ae) {
return ae.Info === "-N/A";
});
var i = 0 ;
_.forEach(stupidService, function (sap) {
oGlobalBusyDialog.setText("Deleting service :" + sap.ObjectID);
oGlobalBusyDialog.setTitle("Deleting Service");
oGlobalBusyDialog.open();
that.removeService(sap).then(function () {
if (i === 615) {
oGlobalBusyDialog.close();
}
}).catch(function () {});
});
my Delete function is like this:
removeService: function (service) {
var that = this;
return new Promise(
function (resolve, reject) {
odataMod.remove('/ProjectTaskServiceCollection(\'' + service.ObjectID + '\')/', {
success: function (oData) {
resolve(oData);
},
error: function (oResult) {
that.handleError(oResult);
oGlobalBusyDialog.close();
reject(oResult);
}
});
});
What's happening ,is that if I'm trying to delete 500 entry, and if 200 entry cannot be deleted, the error message gets displayed 200 times
How to make it in a way to only display the error message once ?
Also, I want to turn off the batch request once everything is done odataMod.setUseBatch(false); how to do it ?
*EDIT: *
I've manage to do :
var aDeffGroup = odataMod.getDeferredGroups();
//add your deffered group
aDeffGroup.push("deletionGroup");
for (var s = 0; s < 5; s++) {
odataMod.remove('/ProjectTaskServiceCollection(\'' + stupidService[s].ObjectID + '\')/', {
//pass groupid to remove method.
groupId: "deletionGroup"
});
}
odataMod.submitChanges({
// your deffered group id
groupId: "deletionGroup",
success: function() {
//Get message model data from Core and it contains all errors
// Use this data to show in dialog or in a popover or set this to your local model see below code
var aErrorData = sap.ui.getCore().getMessageManager().getMessageModel();
console.log(aErrorData);
}
});
yet stills my console.log(aErrorData); still prints multiple error message
Instead of doing individual deletion odata calls. Add these all remove methods in a single group, then call odatamod.submitChanges() method.
Example:
//get all deffered groups
var aDeffGroup = odataMod.getDeferredGroups();
//add your deffered group
aDeffGroup.push("deletionGroup");
//set it back again to odatamodel
odataMod.setDeferredGroups(aDeffGroup);
odataMod.remove('/ProjectTaskServiceCollection(\'' + service.ObjectID + '\')/', {
//pass groupid to remove method.
groupId: "deletionGroup"});
odataMod.submitChanges({
// your deffered group id
groupId:"deletionGroup",
success: function() {
//Get message model data from Core and it contains all errors
// Use this data to show in dialog or in a popover or set this to your local model see below code
var aErrorData = sap.ui.getCore().getMessageManager().getMessageModel();
});

How to get the ID of an inserted record in HANA back to SAPUI5 application?

I got an SAPUI5-application in which I create entries and save them via OData-service. That works, the code for the create operation can be found below. What I have to do now is, I need the ID of the inserted record in HANA back in my application. So what I did I implemented a success handler and thought I would get back this ID in the response from my OData-service. But that is not the case, I get back the same value I provided, in this case 0 since this just a dummy value for the OData-service. I did some research on how to tackle this problem, but none of the approaches worked. So I hope someone of you can help me out or got a hint how to do this. Below the code for create-operation, odata-service and the create.xsjs:
Create-operation in SAPUI5:
this.getOwnerComponent().getModel("Mitarbeiter").create("/ARB", oEntry, {
success: function(oData, response){
console.log(response);
}
});
OData-service:
service {
"MITARBEITERABTEILUNG"."ABTEILUNG" as "ABT" navigates ("Mitarbeiter" as "ARB");
"MITARBEITERABTEILUNG"."Mitarbeiter" as "ARB" create using "public.MitarbeiterAbteilung:mitarbeiterMethods.xsjslib::mitarbeiterCreate";
association "Mitarbeiter"
principal "ABT"("ID")
multiplicity "1"
dependent "ARB"("Abteilung")
multiplicity "*";
}
Create.xsjs:
function mitarbeiterCreate(param) {
let aAfterTableName = param.afterTableName;
var oEntry = {};
try {
var statement = param.connection.prepareStatement("SELECT * FROM\"" + aAfterTableName + "\"");
var rs = statement.executeQuery();
var statement2 = param.connection.prepareStatement('SELECT "MITARBEITERABTEILUNG"."MASEQUENCE".NEXTVAL from dummy');
var rs2 = statement2.executeQuery();
while (rs2.next()) {
oEntry.ID = rs2.getInteger(1);
}
statement2.close();
while (rs.next()) {
oEntry.Name = rs.getString(2);
oEntry.Adresse = rs.getString(3);
oEntry.bz = rs.getString(4);
oEntry.Abteilung = rs.getInteger(5);
}
statement = param.connection.prepareStatement('INSERT INTO "MITARBEITERABTEILUNG"."Mitarbeiter" VALUES (?,?,?,?,?)');
statement.setInteger(1, oEntry.ID);
statement.setString(2, oEntry.Name);
statement.setString(3, oEntry.Adresse);
statement.setString(4, oEntry.bz);
statement.setInteger(5, oEntry.Abteilung);
statement.execute();
statement.close();
} catch (e) {
statement.close();
}
}
Answered in the SAP Community here: https://answers.sap.com/questions/566957/how-to-get-the-id-of-an-inserted-record-in-hana-ba.html
The only thing you need to do, is to update the ID value in the "afterTableName" table provided by the function parameter. Something like that:
let statement = param.connection.prepareStatement('update "' + param.afterTableName + '" set ID = ' + oEntry.ID);
statement.executeUpdate();
Of course that needs to be done after you have determined your new ID. In case your column name is not "ID", please replace it with the real column name.

q promise and map doesn't change after iteration

I'm using Q Promises to retrieve data from my redis repository. The problem I'm having, is that through each iteration, the array object (localEncounter) I'm using to store data returned from the chained functions is never updated at each iteration. Previously, I tried to solve this with a foreach loop and spread but the results were the same.
How should I correct this so that localEncounter is updated at each iteration, and ultimately localEncounters contains correct data when returned? Thank you.
var localEncounters = [];
var localEncounter = {};
Promise.all(ids.map(function(id) {
return localEncounter, getEncounter(id, client)
.then(function (encounter) {
encounterObject = encounter;
//set the fields for the return object
localEncounter['encounterid'] = encounterObject[f_id];
localEncounter['screeningid'] = encounterObject[f_screening_id];
localEncounter['assessmentid'] = encounterObject[f_clinical_assessment_id];
localEncounter['psychevalid'] = encounterObject[f_psych_eval_id];
//get screening
return getScreening(encounterObject[f_screening_id], client);
})
.then(function (screening) {
//set the fields for the return object
localEncounter['screeningbegintime'] = screening[f_begin_time];
//get assessment
return getAssessment(localEncounter['assessmentid'], client);
})
.then(function (assessment) {
//set the fields for the return object
localEncounter['assessmentbegintime'] = assessment[f_begin_time];
//get psycheval
//localEncounters.push(assessment);
return getPsychEval(localEncounter['psychevalid'], client);
})
.then(function (psychEval) {
//set the fields for the return object
localEncounter['assessmentbegintime'] = psychEval[f_begin_time];
localEncounters.push(localEncounter);
}
, function (reason) {
console.log(reason); // display reason why the call failed;
reject(reason, 'Something went wrong creating the encounter!');
})
})).then(function(results) {
// results is an array of names
console.log('done ');
resolve(localEncounters);
})
Solution: I only needed to move the declaration of localEncounter inside the map iterator
before:
var localEncounter = {};
Promise.all(ids.map(function(id) {
after:
Promise.all(ids.map(function(id) {
var localEncounter = {};
This now allows that each id iteration gets its own localEncounter object.

How to create a "loading" spinner in Breeze?

I'm trying to create a loading spinner that will be displayed when breeze is communicating with the server. Is there some property in Breeze that is 'true' only when breeze is sending data to the server, receiving data, or waiting for a response (e.g. after an async call has been made but no response yet)? I thought of binding this data to a knockout observable and binding the spinner to this observable,
Thanks,
Elior
Use spin.js
http://fgnass.github.io/spin.js/
Its so simple..make it visible before you execute the query and disable it after the query succeeds or fails.
I don't see any property that is set or observable while Breeze is querying, but if you are using a datacontext, or some JavaScript module for your data calls, this is what you can do -
EDIT
Taking John's comments into account, I added a token'd way of tracking each query.
var activeQueries = ko.observableArray();
var isQuerying = ko.computed(function () {
return activeQueries().length !== 0;
});
var toggleQuery = function (token) {
if (activeQueries.indexOf(token) === -1)
{ activeQueries.push(token); }
else { activeQueries.remove(token); }
};
var getProducts = function (productsObservable, forceRemote) {
// Don't toggle if you aren't getting it remotely since this is synchronous
if (!forceRemote) {
var p = getLocal('Products', 'Product','product_id');
if (p.length > 0) {
productsObservable(p);
return Q.resolve();
}
}
// Create a token and toggle it
var token = 'products' + new Date().getTime();
toggleQuery(token);
var query = breeze.EntityQuery
.from("Products");
return manager.executeQuery(query).then(querySucceeded).fail(queryFailed);
function querySucceeded(data) {
var s = data.results;
log('Retrieved [Products] from remote data source', s, true);
// Toggle it off
toggleQuery(token);
return productsObservable(s);
}
};
You will need to make sure all of your fail logic toggles the query as well.
Then in your view where you want to place the spinner
var spinnerState = ko.computed(function () {
datacontext.isQuerying();
};

Resources