Javascript object locking? - javascript

I am running into a strange problem with not being able to update properties on an object that is returned as part of a deferred promise.
// Update or Insert status information into the idr_status table
this.updateStatus = function (idrInspData, statusId, submitting)
{
var def = new $.Deferred();
self.getIdrStatus (idrInspData.idr_date).done (function (idrStatus)
{
//status record exists for the day update record
idrStatus.status_msg_id = statusId;
idrStatus.submitted = submitting ? 1 : 0;
idrStatus.modified = 1;
idrStatus.action_needed = statusId.search('+') != -1 ? true : false;
// update the status
self.db.updateRecord (self.idrStatusTableName, idrStatus).always (
function (updateResult)
{
def.resolve(true);
});
}).fail (function (result)
{
def.reject(result);
});
return (def.promise ());
}
The idrStatus object is returned from a SQLite resultset and then converted to a plain JS object then resolved to the done function above. The object comes in but any attempt to edit the properties are simply ignored and the same object is passed Unchanged to the updateRecord function. I am puzzled? Why would the object be locked?

Related

How do I check for a JSON string value in a jS if statement?

I'm calling user data from Memberstack which allows data to be stored as metadata in JSON. I have the following code:
// Set Variables //
var initiated = "Y" <--- demonstration purposes only
var startDate = new Date();
var currentDate = new Date();
// End set variqables. //
// Check initiated state. //
MemberStack.onReady.then(async function(member) {
var metadata = await member.getMetaData()
if (metadata = initiated.includes("Y")) {
runTimer();
} else {
var sDobj = {
startDate: startDate,
}
var initY = {
initiated: "Y"
}
var sDobjjson = JSON.stringify(sDobj);
var initYjson = JSON.stringify(initY);
member.updateMetaData(sDobj, initY)
}
})
// End check initiated state. //
Most of this is working except for the initial if statement (if (metadata = initiated.includes("Y"))) which is currently linked to the variable var initiated = "Y". What I need to do is search the data I have returned under the metadata string response instead of the predefined initiated variable value.
Here is console which correctly returns metadata = {"initiated":"N"} from Memberstack:
Can anybody help me to get my if statement on line 28 if (metadata = initiated.includes("Y")) to read the string value on line 26 metadata = {"initiated":"N"} instead of the predefined variable var initiated = "Y"?
Change this to
if (metadata = initiated.includes("Y")) {
runTimer();
}
This
if (metadata.initiated === "Y") {
runTimer();
}
The issue is that you are assigning the result of the validation to metadata. Also the initiated variable will not be accessible at that line as it is not defined yet

Angular JS: value not updated after assignment

I have a scope that is not updated after assignment inside a factory http call.
var form = {}
var requestForm = {}
requestForm['name'] = $scope.brand.name;
requestForm['country'] = $scope.brand.countryCode;
So I'm setting a $scope.mergeId as my initializer as value 0, then the tableFactory.setMergeRequest will call a http call in the factory file and will return an object, with a boolean and an id #.
$scope.mergeId = 0;
//set merge request/id
tableFactory.setMergeRequest(requestForm).then(function(data){
if(data.mergeRequestStatus){
console.log(data);
$scope.mergeId = data.insertedRequestId; //456
}else{
console.log('no merge id');
}
});
form['mergeId'] = $scope.mergeId;
The boolean will be true, and it should assign the id (456) to the $scope.mergeId. Then that scope will be used to assign the form['mergeId'] variable that will be used in another http call.
When I check the console, the form variable is at zero so it's not updated. I took out the initializer but then it's saying is undefined. The http call is sending back data, it's just the scope is not being updated.
Has anyone gone through this issue before? Should I change the setup for this http call? I tried to this, but it's not setting the right value, it's setting an object.
form['mergeId'] = tableFactory.setMergeRequest(requestForm).then(function(data){
if(data.mergeRequestStatus){
return data.insertedRequestId
}else{
return null
}
});
the response I got from this way, is a d, how do i get the value?
Please help, I've been stuck with this issue for a while. Your help will be appreciated.
ADDITIONAL INFO
This is the http call where tableFactory.setMergeRequest is triggered.
var setMergeRequest = function(object){
var mergeRequestCall = {
method: 'POST',
url: CONFIG.PYTHON_API_END_POINT + '/api/mergerequest',
data: object
}
var d = $q.defer();
$http(mergeRequestCall)
.success(function(response){
d.resolve(response);
}).error(function(response){
d.resolve([]);
});
return d.promise;
}
The response is :
{
"insertedRequestId": 456,
"mergeRequestStatus": true
}
You should set the value where the promise is resolved, not set the value to the function
tableFactory.setMergeRequest(requestForm).then(function(data){
if(data.mergeRequestStatus){
form['mergeId'] = data.insertedRequestId;
}else{
form['mergeId'] = null;
}
});

Javascript function always returns 0

I am writing a function which searches for a value in my IndexedDB and if it finds one, then it should return 1, else it should return 0. The problem is that it always returns 0 though the value exists in a database (variable arr is incremented, but 0 is returned as a result). The code is as follows:
searchAllValues: function(store, type)
{
var arr = 0;
AAA.initDb(function()
{
var obj = {};
AAA.aaaDb.transaction(store).objectStore(store).openCursor().onsuccess = function(store)
{
var storeresult = store.target.result;
if(storeresult.value.value == type ){
arr++;
}else{console.log('value NOT found');}
storeresult ? (obj[storeresult.key] = storeresult.value.value, storeresult["continue"]()) : callback(obj)
}
});if(arr!=0){return 1}else{return 0}
}
EDIT_1:
Ok, I have refactored the code as follows:
addInfo: function(store, type, info)
{
var arr = [];
P4S.p4sPushDb.transaction(store).objectStore(store).openCursor().onsuccess = function(store)
{
var storeresult = store.target.result;
console.log('value of storeresult==>'+storeresult.value.value);
if(storeresult.value.value == info)
{
arr.push(storeresult.value.values);return;//If it finds something it should stop here, no more search or anything to be done
}else
{
console.log('continuing..');
storeresult['continue']();
}
console.log('arr length==> '+arr.length);//If it finds nothing after the looping the whole DB, I want it to print this statement, only once (to send it to my DB actually but sending code is omitted for simplicity).
}
}
Instead I get console.log('arr length==>') statement executed 2 times, for every key in my object store (there are 2 of them actually). So it is doing the code when it finds nothing AND when it finds the value in the DB. Any ideas how to fix it?
Any ideas would be welcome, Thank You
Because by the time the line if(arr!=0){return 1}else{return 0} is executed the db transaction is not complete and value of arr is 0. Though never used indexedDb, but webSql do take some extra miliseconds to read from DB.
Try to put your return logic inside the onsuccess function where you incrementing the arr. You can simply test it by printing value of arr just before your return logic
You need to learn about how to write asynchronous javascript. There are several other indexedDB questions where there are explanations as to why this happens.
For example: Uncaught TypeError: Cannot read property 'transaction' of null with an indexeddb
function addInfo(store, type, info, next)
{
var arr = [];
P4S.p4sPushDb.transaction(store).objectStore(store).openCursor().onsuccess = function(store)
{
var storeresult = store.target.result;
console.log('value of storeresult==>'+storeresult.value.value);
if(storeresult.value.value == info)
{
arr.push(storeresult.value.values);
next(arr);//If it finds something it should stop here, no more search or anything to be done
}else
{
console.log('continuing..');
storeresult.continue();
}
console.log('arr length==> '+arr.length);//If it finds nothing after the looping the whole DB, I want it to print this statement, only once (to send it to my DB actually but sending code is omitted for simplicity).
}
}
Added an extra parameter called 'next' to your the addInfo function.
'next' param is the very last function called if the condition (storeresult.value.value == info) is true.
The next function which you create, will use the 'arr' variable and do whatever with it
your 'return statement' doesnt work the sameway with asynchronous functions, would highly advice you search up asynchronous functions to get a gist of how its different to regular functions
This is how you would call your newly edited function:
addInfo(store,type,info,function(arr){
//do something with arr
})
Note that you have a potential state which would break your code
what if the cursor reaches the end of its iterations and never meets that condition (storeresult.value.value == info). storeresult would be null, and the check for the condition (null.value.value == info) will throw an exception
correction:
function addInfo(store, type, info, next)
{
var arr = [];
P4S.p4sPushDb.transaction(store).objectStore(store).openCursor().onsuccess = function(store){
var storeresult = store.target.result;
if(storeresult){
if(storeresult.value.value == info){
arr.push(storeresult.value.values);
next(arr);
}else storeresult.continue();
}else next();
}
}
And when you call it you handle the scenario whereby arr == null
addInfo(store,type,info,function(arr){
if(arr){
//do something with arr
}else{
//do somethingelse when arr == null
}
})

JSON.parse returns children objects with null value, children values not being parsed

I have a JavaScript object that I am stringifying with JSON.stringify that returns a JSON string with parent and children data.
When I try to parse this string back to an object, the children objects are now null.
function cacheForm(agency) {
var agency = ko.toJS(this); //easy way to get a clean copy
delete agency.contacts; //remove an extra property
for (i in agency.offices) {
for (val in agency.offices[i]) {
//delete agency.offices[i].agency;
//delete agency.offices[i].agencyID;
}
}
for (i in agency.offices) {
for (ii in agency.offices[i].contacts) {
for (val in agency.offices[i].contacts[ii]) {
//delete agency.offices[i].contacts[ii].office;
//delete agency.offices[i].contacts[ii].agencyID;
//delete agency.offices[i].contacts[ii].officeID;
}
}
}
var value = agency;
var cache = [];
parsed = JSON.stringify(value, function (key, value) {
if (typeof value === 'object' && value !== null) {
if (cache.indexOf(value) !== -1) {
// Circular reference found, discard key
return;
}
// Store value in our collection
cache.push(value);
}
return value;
});
var data = JSON.parse(parsed);
}
Edit
Agency part of my view model that I am passing into my cacheForm function and I am using
var agency = ko.toJS(this);
to have my data available in an object which can be parsed to JSON string. I may of deleted this code in my post because my original code had many annotations.
Your question initially showed a screen shot where data.offices = [null] was highlighted.
It's not a parsing error, but an error in stringify. Your paste already has data.offices = [null].
MDN states regarding replacer:
Note: You cannot use the replacer function to remove values from an array. If you return undefined or a function then null is used instead.
And furthermore regarding stringify:
If undefined, a function, or an XML value is encountered during conversion it is either omitted (when it is found in an object) or censored to null (when it is found in an array).
I don't have access to your original object, and hence cannot tell which of the two you are hitting...
Implementing toJSON (or just explicitly constructing another object from the source object) instead of a replacer to filter arrays would be the way to go, if the problem is within your current replacer implementation.
there are various js libraries predefined for parsing json and to get children values . What i usually do to parse json is use http://developer.yahoo.com/yui/json/ YUI library.
So I eventually solved my problem and this is how I did it.
function cacheForm(agency) {
// GET my object from agency vm
var agency = ko.toJS(agency);
var s = YUI().use("json-stringify", function (Y) {
var jsonStrAgency = Y.JSON.stringify(agency, ["activities", "agencyName", "agencyID", "campaignBillings", "category", "declaredBillings", "immediateParent", "numberOfEmployees", "ultimateParent", "uRL"]); // Use an array of acceptable object key names as a whitelist.
var jsonStrOffices, jsonStrContacts;
for (i in agency.offices) {
jsonStrOffices = Y.JSON.stringify(agency.offices, ["address1", "address2", "address3", "address4", "address5", "agencyID", "faxNumber", "officeID", "postCode", "telephoneNumber"]);
for (ii in agency.offices[i].contacts) {
jsonStrContacts = Y.JSON.stringify(agency.offices[i].contacts, ["agencyID", "emailAddress", "firstName", "jobName", "officeID", "personID", "surName", "title"]);
}
}
localStorage.setItem('Agency', jsonStrAgency);
localStorage.setItem('Offices', jsonStrOffices);
localStorage.setItem('Contacts', jsonStrContacts);
});
}
Firstly I am passing in my ko.observableArray to the function cacheForm. This parameter is called agency and it is part of my viewmodel.
I want to parse my observableArray and convert it into a standard javascript object. By using ko.toJS I can do this. There will be no ko constructors after using toJS.
Then I have to get my JSON strings. Since my object has children and grandchildren I have to parse these parts separately. Stringify doesn't like arrays within an object, they will be changed to null and your children data will be lost.
Because of circular recursion, I have to use this:
var s = YUI().use("json-stringify", function (Y) {
This is part of the Yahoo API. This is the script reference:
<script src="http://yui.yahooapis.com/3.11.0/build/yui/yui-min.js"></script>
Y.JSON.stringify takes an object as one parameter and an option paremter which is an array. The purpose of this array is to contain the property names of the object you want to stringify. From other forums I found out this is known as whitelisting.
With all my JSON strings I can store them in HTML5 local storage.
When the page loads I then check to see if my local storage contains data. If true I retrieve my data and serialize from JSON string to a javascript object.
define(['services/datacontext'], function (dataContext) {
var initialized = false;
var agency;
if (localStorage.Agency && localStorage.Offices && localStorage.Contacts) {
var objAgency = new Object(ko.mapping.fromJSON(localStorage.getItem('Agency')));
var objOffices = new Object(ko.mapping.fromJSON(localStorage.getItem('Offices')));
var objContacts = new Object(ko.mapping.fromJSON(localStorage.getItem('Contacts')));
objAgency.offices = objOffices;
objAgency.offices._latestValue[0].contacts = objContacts;
agency = ko.observableArray([ko.mapping.fromJS(objAgency)]);
ko.applyBindings(agency);
initialized = true;
}
else {
agency = ko.observableArray([]);
}
Finally I reconstruct my object to how it was before stringify and map it back to an observableArray and finally bind it.
Hopefully this helps other people using a combination of knockoutJS and complicated objects.
See below for my full code:
define(['services/datacontext'], function (dataContext) {
var initialized = false;
var agency;
if (localStorage.Agency && localStorage.Offices && localStorage.Contacts) {
var objAgency = new Object(ko.mapping.fromJSON(localStorage.getItem('Agency')));
var objOffices = new Object(ko.mapping.fromJSON(localStorage.getItem('Offices')));
var objContacts = new Object(ko.mapping.fromJSON(localStorage.getItem('Contacts')));
objAgency.offices = objOffices;
objAgency.offices._latestValue[0].contacts = objContacts;
agency = ko.observableArray([ko.mapping.fromJS(objAgency)]);
ko.applyBindings(agency);
initialized = true;
}
else {
agency = ko.observableArray([]);
}
var save = function (agency, myStoredValue) {
// Clear Cache because user submitted the form. We don't have to hold onto data anymore.
//amplify.store("Agency", null);
return dataContext.saveChanges(agency);
};
var vm = { // This is my view model, my functions are bound to it.
//These are wired up to my agency view
activate: activate,
agency: agency,
title: 'agency',
refresh: refresh, // call refresh function which calls get Agencies
save: save,
cacheForm: cacheForm
};
return vm;
function activate() {
vm.agency;
if (initialized) {
return;
}
initialized = false;
return refresh();
}
function refresh() {
return dataContext.getAgency(agency);
}
function cacheForm(agency) {
// GET my object from agency vm
var agency = ko.toJS(agency);
var s = YUI().use("json-stringify", function (Y) {
var jsonStrAgency = Y.JSON.stringify(agency, ["activities", "agencyName", "agencyID", "campaignBillings", "category", "declaredBillings", "immediateParent", "numberOfEmployees", "ultimateParent", "uRL"]); // Use an array of acceptable object key names as a whitelist.
var jsonStrOffices, jsonStrContacts;
for (i in agency.offices) {
jsonStrOffices = Y.JSON.stringify(agency.offices, ["address1", "address2", "address3", "address4", "address5", "agencyID", "faxNumber", "officeID", "postCode", "telephoneNumber"]);
for (ii in agency.offices[i].contacts) {
jsonStrContacts = Y.JSON.stringify(agency.offices[i].contacts, ["agencyID", "emailAddress", "firstName", "jobName", "officeID", "personID", "surName", "title"]);
}
}
localStorage.setItem('Agency', jsonStrAgency);
localStorage.setItem('Offices', jsonStrOffices);
localStorage.setItem('Contacts', jsonStrContacts);
});
}
});

How to create a call back function and store the value of the variable

I am reading a Rss feed using setInterval method and displaying notification to the users ,I want to make sure I store the latest feed title so that the user does not get multiple notification of the same title again. The current implementation does not work because I cant use that variable until the response comes back. To make things worse I am delaying the execution.So I am guessing I need to use callback function get the value and do my checking inside that function. I am not able to figure out how to do the callback and get the value of entry_title.
/** global variable **/
var global_Rsstitle;
/** end global variable **/
function get_rss1_feeds() {
var Rss1_title = getRss("http://rss.cnn.com/rss/cnn_topstories.rss", function(entry_title) {
if(global_Rsstitle != entry_title)
global_Rsstitle = entry_title;
console.log('test',global_Rsstitle); // the value is outputed but global var is not working
});
console.log('test1',global_Rsstitle); // outputted as undefined ??
}
google.load("feeds", "1");
google.setOnLoadCallback(function () { setInterval(get_rss1_feeds, 5000); });
My jsRss.js
function getRss(url, callback){
if(url == null) return false;
// Our callback function, for when a feed is loaded.
function feedLoaded(result) {
if (!result.error) {
var entry = result.feed.entries[0];
var entry_title = entry.title; // need to get this value
callback && callback(entry_title);
}
}
function Load() {
// Create a feed instance that will grab feed.
var feed = new google.feeds.Feed(url);
// Calling load sends the request off. It requires a callback function.
feed.load(feedLoaded);
}
Load();
}
can u see the entry_title -> this stores d value i need
so i need to get this value n store it into a global variable
or send it to another fns as a argument
so that I can maintain the value
and when next time setInterval is fired
I get a new value so I can compare and check if its same
n if its same I dont display it to the user
google.load("feeds", "1");
google.setOnLoadCallback(function () {
var oldTitle = '',
newTitle = '',
getRss = function (url, callback) {
(url) && (function (url) {
var feed = new google.feeds.Feed(url);
feed.load(function (result) {
(!result.error && callback) && (callback(result.feed.entries[0].title));
});
}(url));
};
setInterval(function () {
getRss(
'http://rss.cnn.com/rss/cnn_topstories.rss',
function (title) {
newTitle = title;
if(oldTitle !== newTitle) {
oldTitle = newTitle;
console.log('oldTitle: ', oldTitle);
}
console.log('newTitle: ', newTitle);
}
);
}, 5000);
});

Categories

Resources