Javascript SessionStorage Checking Before Running a Function - javascript

I have a function that I'm calling. Called getStatus(). But this function requires there to be a defined SessionStorage variable that could be present. If the variable is present then I want to go ahead and execute the getJob() function. If it's not present I want to try to define the SessionStorage variable and then execute the getJob() function.
Like this:
function getStatus()
{
if (sessionGet("jwt") != null)
{
getJob(document.getElementById('job').value, document.getElementById('id').value);
}
else
{
var myValue = '{{ myValue }}';
console.log("Token is missing, acquiring another one!");
var nextToken = setTimeout(function(){ getSessionToken(myValue); }, 5000);
console.log("Reissued token issued is");
console.log(nextToken);
getJob(document.getElementById('job').value, document.getElementById('id').value);
}
}
And here is the function that reads the SessionStorage variable:
function sessionGet(key) {
let stringValue = window.sessionStorage.getItem(key)
if (stringValue !== null) {
let value = JSON.parse(stringValue)
let expirationDate = new Date(value.expirationDate)
if (expirationDate > new Date()) {
return value.value
} else {
window.sessionStorage.removeItem(key)
}
}
return null
}
When I look at the Chrome console I see the SessionStorage variable being written, but the getJob() function that reads the variable doesn't see it. If I retry then the getJob() function is able to read it. My thought is that the getJob() function is firing before the variable has been written. That's why I tried the setTimeout() in there.
Any suggestions?

As ztadic91 pointed out, I needed to wrap the setTimeout around the getJob() function call, since it needed to wait for the SessionStorage variable to be created. After doing that things tested out fine. Appreciate the quick assist!

Related

Setting data in Local Storage/function usage

I'm attempting to simply save a string to Chrome's Local Storage, but I can't seem to do it. It could be that I've got the wrong idea about function argument implementation (after 3 years, I think I might be getting it) but any help getting this code to work would be appreciated. I wanted to make it as dynamic as possible, allowing me to take the id of any text input field I write and change the stored string appropriately.
Here's the code I've got so far:
function setData() {
dataToStore = document.getElementById('txtStore').value;
return dataToStore;
}
function storeData(data) {
localStorage.setItem('input', data);
}
btnStore.addEventListener('click', storeData(setData), false);
Is my implementation of function arguments a bit backwards? I really thought I had it this time..
When you write:
btnStore.addEventListener('click', storeData(setData), false);
storeData(setData) is executing immediately at the beginning (when you bind the click event). Therefore, it will pass the initial value of your input which is probably empty.
So you should call setData, when you store the Data:
function setData() {
dataToStore = document.getElementById('txtStore').value;
return dataToStore;
}
function storeData() {
localStorage.setItem('input', setData());
}
btnStore.addEventListener('click', storeData, false);
you would have to do this:
function setData() {
dataToStore = document.getElementById('txtStore').value;
return dataToStore;
}
function storeData(dataFunct) {
localStorage.setItem('input', dataFunct());
}
btnStore.addEventListener('click', storeData(setData), false);
you can use without argument
function setData() {
dataToStore = document.getElementById('txtStore').value;
return dataToStore;
}
function storeData() {
var data = setData();
localStorage.setItem('input', data);
}
btnStore.addEventListener('click', storeData(), false);
You're saving the value in setData, which is a function, not the value returned from the function. You have to invoke the function to get the return value.
function storeData(data) {
vare returnedData = data()
localStorage.setItem('input', data);
}
with your current code you'd have to use the above snippet. But it would make more sense to retrieve the data before invoking storeData, and not pass the function.
You need to differentiate between function invocations and function references.
btnStore.addEventListener('click', storeData(setData), false);
An event is assigned a callback - i.e. reference to a function - but you're passing it the return value of setData, which is a string, not a function.
function setData() {
dataToStore = document.getElementById('txtStore').value;
return dataToStore;
}
function storeData() {
localStorage.setItem('input', setData());
}
btnStore.addEventListener('click', storeData, false);
You should simplify it a bit using more descriptive names for your functions:
function getDataFromElement(id){
dataToStore = document.getElementById(id).value;
return dataToStore;
}
function storeData(data) {
localStorage.setItem('inputData', data);
}
function retrieveData() {
return localStorage.getItem('inputData');
}
btnStore.addEventListener('click', storeData(getDataFromElement('txtStore')), false);
This way is more generic and you can even reuse it for other elements, improve it turning that 'inputData' into a parameter.
You could also add a check to verify that local storage is available before using it:
function canStorage(){
return (typeof(Storage) !== "undefined") ? true : false;
}
It is a good idea to batch your reads and writes, say one read per page and one write per page unload. It does depends on your use case, however, storing data in memory ie. data structure until some less frequent commit action.
To write data to Window.localStorage.
localStorage.setItem(k, v);
To read data from storage
localStorage.getItem(k);
Update:
A snippet of a module I wrote in gist which provides basic functions such as;
get
set
delete
flush
has
and a few chainable functions.
Hope this helps.

explain javascript: value assignment fails

var sc = new stuCore();
function stuCore() {
this.readyPages = [];
this.once = true;
var self = this;
// gets called asynchronously
this.doPrepPage = function (page){
if(self.once == true){
// still gets executed every time, assignment fails
self.once = false;
doSomeStuffOnce();
}
};
this.addReadyPage = function (pageid) {
console.log("readypage called");
this.readyPages.push(pageid);
if (!$.inArray(pageid, self.readyPages) != -1) {
this.doPrepPage(pageid);
}
};
}
why does this assignment fail? I thought I knew the basics of js, but I'm stumped by this. And furthermore what would be a possible solution? call a constructor first and set the variable there?
EDIT:
gets called like this in some other script:
sc.addReadyPage(self.id);
The jQuery.inArray function will return the index in the containing array for the given value. Your script pushes pageid into this.readyPages before checking whether it exists in self.readyPages. this.readyPages and self.readyPages are the same array reference, so the result will always be zero or greater, so the condition that calls doPrepPage will never run.
You could try switching their order around:
this.addReadyPage = function (pageid) {
console.log("readypage called");
if ($.inArray(pageid, self.readyPages) != -1) {
this.readyPages.push(pageid);
this.doPrepPage(pageid);
}
};
(edit: Removed the additional !, thanks #chumkiu)
If I understand correctly you're calling this.doPrepPage as <insert variable name here>.doPrepPage?
If this is the case then your var self passes through to the anonymous function and is stored there, so everytime you call this.doPrepPage it takes the local variable of self.
Try setting self to a global variable, this way it will permanently modify self so each time this.doPrepPage is called it uses the updated variable.

Calling nested function from nested setInterval in an Object Namespace environment

I have this following piece of code:
var stats = {
....,
checkExistance :
function(url){
var newUrl = url.substring(0, url.lastIndexOf("/")) + "/asyncCheckChartExistance";
var xhrObj = stats.getXhr();
var poolInterval = setInterval("poll()", 100);
function poll(){
xhrObj.open("GET", newUrl, true);
xhrObj.send(null);
xhrObj.onreadystatechange = function(){
if(xhrObj.readyState === 4 && xhrObj.status === 200){
if (xhrObj.responseText.length === true){
console.log("Exists!");
clearInterval(poolInterval);
} else {
console.log("Not Yet!");
}
}
}
}
},
}
I created the stats namespace. In this namespace I'm trying to create a function which polls the server every second. I should access this function this way: stats.checkExistance(myUrl).
However it seems that the setInterval function is not able to see the poll() function. I know that this is normal behavior taking in consideration that these are nested inside another function.
If I were to write this in the Global namespace there would be no problem but I'm interested to make this work in this kind of namespace. Any ideas? Thanks!
when you pass a string to setInterval, it runs in the global scope, by default, where poll would not be defined since it only exists in the scope of the checkExistance function.
To fix the issue, pass an anonymous function to setInterval instead:
var poolInterval = setInterval(function () {
poll();
}, 100);
Passing an anonymous function is usually the best idea as it allows you to write any javascript expressions/statements for the interval instead of just calling one function.
When you pass a string to setInterval, that string is interpreted as global code, and since poll is not a global function, a reference error is thrown.
However, you can pass a function reference instead of a string, and since the poll function is available in the scope in which the setInterval invocation is made, you can just write this:
var poolInterval = setInterval( poll, 100 );
var stat = {
say: function(name){
function doit(){
console.log(name);
}
setInterval(doit, 1000);
}
};
stat.say("hi");​​​​​​​​​​​
A simple demo to show how. You will see "hi" every second.

Why does this JavaScript function always returns 'undefined' – and how to fix that?

I'm using phonegap with application preferences plugin and trying to make a helper function to get a value from it. However the function is not returning a correct value. I know this has to do with asynchronous thingy but unfortunately I don't know how to fix it. (I've tried to search help here, and found little, and tried to implement it in helper method)
What I want to achieve is:
function populateList() {
var a = 1;
var number = getSettingFromApplicationPreferences('number');
// number is always undefined
var letter = getSettingFromApplicationPreferences('letter');
// letter is always undefined
number = (number) ? number : 1;
letter = (letter) ? letter : 'b';
// Here I'll do some DOM manipulation and use 'number' and 'letter' on it, and
// define new variables based on 'number' and 'letter'
}
here's the helper function that I need help with:
function getSettingFromApplicationPreferences(setting) {
var x = (function () {
window.plugins.applicationPreferences.get(
// setting
setting,
// success callback
function(returnValue) {
console.log(setting + ': ' + returnValue);
return returnValue;
},
// error callback
function(error) {
alert("Failed to get a setting: " + error);
return false;
}
);
})();
return x;
}
Question
How is it possible to return the 'returnValue' from application preferences with that helper function?
The problem is, your callback doesn't actually set a value for x. So, you're going to have some other way to do whatever you're doing, because return values will not work.
You are using an asynchronous function incorrectly, you cannot assign like you are because the function hasn't returned yet and so you get an undefined. You need to use a callback function instead.
That means that inside the success function you would do whatever you need to do with the "returnValue".

Possible to stop a Javascript function with another Javascript call?

I am having a problem where I want to stop a particular function from executing. This function is located on another plugin which I can't change the core files so I am wondering if I can stop a specific function from that file from executing?
So for example that function is testFunction(); and I want to stop that later in the code maybe in on document ready...etc.
Thanks!
Is the function public (as opposed to private via a closure)? And, does it need to be operational at all for things to work, or can you chop it out in total and be fine? If the latter, you can replace the function with a new one:
otherLibrary.testFunction = function(){};
If you want to disable it for a temporary amount of time, you can store the function in a temporary variable, and restore it later:
var removedFunc = otherLibrary.testFunction;
otherLibrary.testFunction = function(){};
// do something, time passes, whatever...
otherLibrary.testFunction = removedFunc;
Or, if you want to be able to toggle it, a slight variation:
var removedFunc = otherLibrary.testFunction;
var testFunctionEnabled = true;
otherLibrary.textFunction = function(){
if(testFunctionEnabled){
removedFunc.call(this, arguments);
}
};
And then just set testFunctionEnabled as you need to.
you should try to extend the function before you call it e.g.
$.extend(plugin.function, myNewFunction);
also, check the plugin API to see if you can pass a paramter to override the function or actually access the api of the plugin e.g.
$('#mytip').api('hover', myHoverFunction);
If you have access to the object which refers to the "testFunction" function then you could replace it with an empty function, e.g.:
SomePlugin.testFunction = function() { };
Ultimately, if you don't have a way to overwrite that symbol then there's not much you can do to stop the method from running (unless you can provide more details).
If that function schedules itself with setInterval, you can use clearInterval(thefunction) to prevent it from being called again. But if it's a loop, I don't know if that's possible.
Simply set the function to null.
JavaScript example:
function write() {
el.innerHTML += 'Lorem ipsum dolor sit amet.<br />';
if (execute != null) execute();
}
function execute() {
setTimeout(function() { write() }, 500);
}
function abort() {
execute = null;
}
window.onload = function() {
el = document.getElementById('blah');
execute();
}
HTML:
<button type="button" onclick="abort()">Abort</button>
<p id="blah"></p>
Also you can change the following to implement stop/start. For this, assign the execute function to a variable so that you can later assign that variable back to execute.
var oldfunc = execute;
function abort() {
if (execute == null) {
execute = oldfunc;
execute();
} else {
execute = null;
}
alert(execute);//shows the function code
}
You can overwite any method you have access to- but if the code in your module calls it internally you better give it an appropriate return.
document.write=function(){return true};
alert(document.write('tell me more!'))

Categories