I am working on a react-flux app where I am using sessionStorage to keep a user logged in by checking if email and auth token are available in sessionStorage. If they are available and time since login is less than 15 minutes, I trigger off a flux action to log the user in. I also have another function that irrespective logs the user out after 15 minutes by clearing out the sessionStorage.
It works fine, until I refresh the page. At this point, the setInterval function that logs the user out after 15 minutes, resets itself.
Here's the code to make sense of what I am referring to:
In my parent component I have the following functions that I call inside componentDidMount function.
checkSession: function() {
if (!_.isNull(window.localStorage)) {
var currentTimeStamp = Date.parse(new Date());
var logInStamp = window.sessionStorage.time;
var difference = currentTimeStamp - logInStamp;
if (Math.floor((difference / 1000) / 60) < 15) {
var data = {
email: window.sessionStorage.email,
scheduler_slug: window.sessionStorage.slug
};
ActionCreator.loginUser(data);
}
}
},
logOut: function() {
if (this.state.isLoggedIn === true) {
window.sessionStorage.clear();
ActionCreator.logOutUser();
}
},
componentDidMount: function() {
Store.addChangeListener(this._onChange);
this.checkSession();
setInterval(this.logOut, 900000);
}
I am setting the key values for sessionStorage on success of my ajax call for creating a session. In subsequent api calls, i send back the token i received in response from the first call in my response header for authentication.
My question is 2 fold:
1) Is my current approach enough to maintain user session? Would using cookies be better?
2) If my current approach is fine, then I need to figure out a way to prevent timer from resetting on page refresh which I thought would be an easy fix but everything I am seeing involves using cookies. Is there another way?
This is very subjective. If this approach works for you, that is ok. Cookies are also a good option for this, it just depends. You mention that you have some troubles using your current approach (mostly on page refresh). A cookie could help, but isn't some silver bullet either. Choose wisely what fits your app the best (think about if you ever want your server calls to be called from libraries etc, which might introduce more annoyances when using cookies.
Since you already store something in the sessionStorage, you can also choose to store the data simply in localStorage. This will ensure it stays the same, and since the time is saved as well you're basically providing your own session storage, that survives a refresh.
A side note, sessionStorage shouldn't reset itself on a refresh, it lives in a tab-context. So if you open a new tab you do get a new session, if you refresh you should be having the same storage. Depending on your app you might want to take a look if you somewhere replace the data, or if the refresh happens in a different tab.
Related
I am looking to display a page every N days or for example every 3/4 days which will just popover the screen
So far from digging about I see ionics local notifications offers a really nice way to schedule standard notifications within an app but it does not allow you to change the notification data to use a page.
Is there a way to do this kind of thing natively within ionic ?
Does it need to be a popover? Couldn't you just keep a record of the last time the page was show to the user using localStorage or Storage and when the app is launched check if it's time to show the page again and then redirect to that page. If you do want it to be a popover it's pretty simple. You create the page like normal then add it as the component in your poperover constructor. Something like this in your platform.ready():
const daysSinceLastShown = parseint(localStorage.get('daysSinceLastShown'), 10);
if (daysSinceLastShown < 4) {
daysSinceLastShown++;
localStorage.put('daysSinceLastShown', daysSinceLastShown);
} else {
localStorage.put('daysSinceLastShown', 0);
presentPopover();
}
async presentPopover() {
const popover = await this.popoverCtrl.create({
component: MyPopoverPage,
});
return await popover.present();
}
I'm trying to make a code which lets me show how much a certain part of my website has been views.
My problem is, when I fresh refresh, it goes back to zero, instead of 2. I hope you can help me out. I want the code to run forever, or as long as I want it to, and it will just add a 1 to what it has been, even if it was yesterday. Here's the sample of the code.
<script type="text/javascript">
var bannerViews = 0;
function addViews (){
bannerViews = bannerViews + 1;
}
addViews();
</script>
<p>This banner has been viewed <script type="text/javascript">document.write(bannerViews);</script> timesĀ </p>
Hope you can help me out.
It is because every time you refresh your page, your code reinitializes. In-order to persist the data, you need to store it somewhere. Either in a cookie or a localstorage.
If you go ahead with the localstorage, here's how you do it.
var bannerViewCount = localStorage.getItem('bannerViews');
if(!bannerViewCount) {
bannerViewCount = 0;
}
function addViews() {
localStorage.setItem('bannerViews', ++bannerViewCount);
document.body.innerHTML = 'Banner view count is :' + bannerViewCount;
}
addViews();
Demo (click on Run on the top bar multiple times and see it incrementing)
Here, what am doing is first, fetching the banners view count. If I don't get it, I initialize it with zero.
Later, I on addViews() call, I increment the bannerViewCount by one and store it to the localStorage. That's it.
Note that the data is stored in your local storage, so if you are expecting that the count should be visible to other users too, you need to store it in a database or a text file and later parse it.
If you want to store it on the cloud, so that you can share the count across the visitors, you can do something like this.
function addViews() {
$.get('//jsonbin.io/b/5974382ca489d40388582791/latest', function(data) {
var bannerViewCount = data.bannerviews;
$.ajax({
url: '//jsonbin.io/b/update/5974382ca489d40388582791',
type: 'post',
dataType: 'json',
data: {
snippet: JSON.stringify({
bannerviews: ++data.bannerviews
})
},
success: function(fetch) {
var data = fetch.data;
document.body.innerHTML = 'Banner view count is : ' + JSON.parse(data).bannerviews;
}
});
});
}
addViews();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Click on "Run Code Snippet" button and see the counter incrementing. Go to any other browser and the count will persist as expected. Note that the data stored here can be manipulated as there is no authentication in place. So avoid it if you want the count to be precise and legit.
It goes back to 0 because the variable bannerViews is reinitialised to 0 on every page load.
You will need to store this variable in a JSON file/DB and fetch/update the value there.
Every time you refresh the page the code is going to be reset and variables are included.
To solve this you have to either use a web server and have the variable saved there or find a way to save the variable to the filesystem and load it
back.
The reason the counter is reset constantly is because you're declaring the variable during runtime. There is no persistence to the variable so every time the website is loaded, the variable starts against from 0. Each browser client would keep track of the variable separately so even if you were able to get the variable to persist on your local browser, you would not be able to keep track of the page views from other browsers. The solution to this problem is to keep track of the page views from a centralized server.
You can use a free service such as http://www.webestools.com/pages-views-counter-free-number-pages-views-statistics.html to create the counter that would persist between page views and different clients.
What you need to do is to get the initial value 0 , store in on the server , database or file.
change line var bannerViews = 0; to something like;
var bannerViews = getValueFromServer();
and every after re assigning it, you store it back to the external storage;
For now everytime you refersh the page .
the code var bannerViews = 0; will run and hence bannerViews will alwayz be re assigned to 0
I have a JSON data of news like this:
{
"news": [
{"title": "some title #1","text": "text","date": "27.12.15 23:45"},
{"title": "some title #2","text": "text","date": "26.12.15 22:35"},
...
]
}
I need to get a certain number of this list, depended on an argument in a function. As I understand, its called pagination.
I can get the ajax response and slice it immediately. So that every time the function is called - every time it makes an ajax request.
Like this:
function showNews(page) {
var newsPerPage = 5,
firstArticle = newsPerPage*(page-1);
xhr.onreadystatechange = function() {
if(xhr.readyState == 4) {
var newsArr = JSON.parse(xhr.responseText),
;
newsArr.news = newsArr.news.slice(firstArticle, newsPerPage*(page));
addNews(newsArr);
}
};
xhr.open("GET", url, true);
xhr.send();
Or I can store all the result in newsArr and slice it in that additional function addNews, sorted by pages.
function addNews(newsArr, newsPerPage) {
var pages = Math.ceil(amount/newsPerPages), // counts number of pages
pagesData = {};
for(var i=0; i<=pages; i++) {
var min = i*newsPerPages, //min index of current page in loop
max = (i+1)*newsPerPages; // max index of current page in loop
newsArr.news.forEach(createPageData);
}
function createPageData(item, j) {
if(j+1 <= max && j >= min) {
if(!pagesData["page"+(i+1)]) {
pagesData["page"+(i+1)] = {news: []};
}
pagesData["page"+(i+1)].news.push(item);
}
}
So, simple question is which variant is more effective? The first one loads a server and the second loads users' memory. What would you choose in my situation? :)
Thanks for the answers. I understood what I wanted. But there is so much good answers that I can't choose the best
It is actually a primarily opinion-based question.
For me, pagination approach looks better because it will not produce "lag" before displaying the news. From user's POV the page will load faster.
As for me, I would do pagination + preload of the next page. I.e., always store the contents of the next page, so that you can show it without a delay. When a user moves to the last page - load another one.
Loading all the news is definitely a bad idea. If you have 1000 news records, then every user will have to load all of them...even if he isn't going to read a single one.
In my opinion, less requests == better rule doesn't apply here. It is not guaranteed that a user will read all the news. If StackOverflow loaded all the questions it has every time you open the main page, then both StackOverflow and users would have huge problems.
If the max number of records that your service returns is around 1000, then I don't think it is going to create a huge payload or memory issues (by looking at the nature of your data), so I think option-2 is better because
number of service calls will be less
since user will not see any lag while paginating, his experience of using the site will be better.
As a rule of thumb:
less requests == better
but that's not always possible. You may run out of memory/network if the data you store is huge, i.e. you may need pagination on the server side. Actually server side pagination should be the default approach and then you think about improvements (e.g. local caching) if you really need them.
So what you should do is try all scenarios and see how well they behave in your concrete situation.
I prefer fetch all data but showing on some certain condition like click on next button data is already there just do hide and show on condition using jquery.
Every time call ajax is bad idea.
but you also need to call ajax for new data if data is changed after some periodic time
I will put this post into paragraphs to make it easier reffering to specific content.
I have made a simple button in html that plusses a number with 1 everytime the button is pressed. This function is made in Javascript. This number has to be put into the database every 20 seconds.
Since Javascript is running on the client side, every visiter will be able to change the current number of times the button is pressed, and that "fake" number will then be sent to the database after 20 seconds.
The user should not be able to change this number, because it's considered cheating.
I could use other languages to complete this like java, flash etc. but I need to make it working with Javascript/Jquery that runs on the client side. The reason for this is that it will take too hard on the server if there is sent a request to the server everytime to button is pressed.
I hope you understand all 4 steps, if not please let me know which step I shall deepen.
Question: How can I make a secure way of processing a number from the client-side to the database without the user being able to change that number on their computer? If I can't, any other suggestions?
Thanks in advance.
First of all, your counter should be on your server. Don't let the client side tell you how many times the button has been pressed - store this yourself on the server (where no one can reach).
This will mean that you'll have to notify the server every time the user clicks the button. Furthermore, you'll need to make sure that each "click" is valid. You could do this by attaching a unique key to each of the buttons clicks. As soon as the user clicks the button, this key will be sent to the sever and validated. If it is valid, the server will return a new key to be sent when the button is next clicked.
You should be aware that it is very VERY easy to write a short jQuery script to manipulate clicks on DOM elements though. A command as simple as
setInterval(function(){
$('button').trigger('click');
},500);
Would trigger a click event on the button every 500 milliseconds (0.5 seconds).
Code that runs in JavaScript can't practically be protected against "cheating". Your best bet might be data hiding:
var myobj = (function() {
var i = 0;
return {
function setI(newvalue) {
// do checks here
if (true) {
i = newvalue;
}
},
function sendI() {
// send value of i
}
}
}());
myobj.setI(123);
myobj.sendI();
myobj.i // undefined
Moving the logic that prevents data tampering to the server is better though.
We have a intermittent bug that it's been hard to track, the bug consists in randomly (so we think) when redeeming a code, the entire code value disappears upon making the order...
Doing our self the same process manually, it does not, never ever, happen!
So I thought recording the user actions, every action:
click links
submit inputs
page views
ended up making up this set of rules, and appending to the end of the master page:
$(function() {
// log this page view
log2Loggly('Page View', '');
// for each click
$("a").click(function() {
var ref = $(this).attr("onclick").length > 0 ? $(this).attr("onclick") : $(this).attr("href");
log2Loggly('Link clicked', ref);
});
// forms
$("form").submit(function() {
var dt = $(this).serialize();
log2Loggly('Form submited', dt);
});
});
and using Loggly I can send each action, as they get the hold of the date and IP, it's easier to match a user IP upon our system.
I keep seeing this services like CrazyEgg that record all user actions, but we can't match the user, it's anonymous data!
What I really liked was to search for IP and get the entire user tree as kind'a of an organigram of what the user did... maybe I'm able to pull this off with the data I have, but I would like to ask 2 things prior to adventure on this idea
Is there any kind of service for this outthere that you might come across before?
what more should I track to make it "almost perfect"?