Saving state of webpage with socket.io - javascript

I am creating a card game with node.js as the server , and i'm using web sockets (socket.io) to transfer the data from server to client .
so after the cards are dealt i want if someone refreshes the page he can see the current state of the game , in my case he just see nothing the cards are not dealt and there are no players . so is there some way to save the state of the game whenever a player refreshes the pages he can see all the changes that happen to the html page .

One way you can do it is to have the actual game state on the server. That way, when the user reloads the page, the page simply requests the state back from the server. This basically means that the game is actually on the server, and your clients are merely "remote controls" to the game on the server.
Another way is to save the state locally, using local storage. However, there could have been changes between the last time the user was on the game and during his return (like a card dealt, or a card drawn, a card passed etc.).
You can even use both. Where you read the local storage for the state first. That way, you have your hand state before you left. You can then request the server for the changes, and animate the game accordingly.

Related

How to handle authentication flow in a React Web App?

I would like to discuss a paradigm that I am following for the authentication flow in a React Web App and need your advice / suggestions on the same.
The app has a button in the top right corner which is rendered
conditionally based on user’s auth status. If a user is signed in, the
button says Hi, first name on click of which the user can access
protected routes else it’s just a Login button.
Current flow:
Every time user access the app, a spinner displays before rendering the actual route till user’s auth status is being detected by Firebase’s onAuthChanged() which takes a few seconds.
Once onAuthChanged() conveys the auth status, app renders the route with the button in top right corner based on auth status.
Issue with the current flow:
Above mentioned flow doesn’t feel like a seemless experience for the user. Because every time user is accessing the app again or even refreshes its browser, it has to wait for that annoying spinner to go away. This is a pretty bad user experience.
Most of the app can be interacted irrespective of auth status, so it doesn't make sense to display a spinner across entire app even if it’s a public route just because auth status needs to be known in order to conditionally render that button. This flow makes the app completely unusable until the auth status is not detected by Firebase. Plus, as all the routes are lazy loaded, it adds up time for user to access app for first time with the 1st spinner being displayed as a fallback for lazy loading the route and the second one for the auth status.
Solution to current flow:
I have thought of a solution which can help me with above. What I am thinking now is to shimmer that button till the auth status is being detected by Firebase. And this seems like a pretty neat solution because now use can interact and browse the app while the button is being shimmered.
Drawbacks of the solution:
But this button is actually not alone in upper right corner and is accompanied by three other buttons as well which link to some other public routes.
So, it’ll make UI quite inconsistent by shimmering only that one button, so I’m thinking that I can shimmer all four of them. But this even might seem annoying to user that the entire app loads quickly on refresh, but the upper 4 buttons still shimmer for few seconds and it cannot access any of those to access other public routes.
Alternate solution:
There’s a third and last iteration to the solution, in which I’m thinking to cache the auth status as a boolean check in local storage whether it’s logged in or not along with it’s first name. Now, the app will be totally seemless on browser refresh and repetitive app access.
Caveats:
But, let’s suppose the user has changed his first name on other device and user accesses the app on this browser, the button will show it’s old name cached in the local storage. To sync the name, I’ll have to store the updated name from onAuthChanged() in local storage, update in redux from local storage and then display it on the button. Now, this will seem like a bug to user and might report as well because the old name will flash for a few seconds till the updated name doesn't come from the onAuthChanged()
CONCLUSION: I’d be like to know your views or if you have a better flow than these above. Thanks! :)
Your Alternate Solution is the best bet according to me.
Even if your user changes name on some other device, once the user logs in on web it will first fetch from localStorage and then due to onAuthChanged() it would give the user old name only for a few second and then display the new name.
Its not like user is going to change the name often, it will be only once in a while and few seconds to update the name once in a while would not be a big issue.

Updating localStorage when there's new data from server?

After logging into an app (React.js), I am caching the member data in localStorage as a lot of my components are using it and request only needs to be done upon log-in, ideally.
However, a few properties in this member object may be changed in the backend manually so the frontend doesn't have a way to know whether the member object has changed at all. (Again, ideally, any change to the member object should go through some form submission that directly changes the DB, with which an update can be triggered for the localStorage, but this is not an option at this time.)
Example scenario: There's a generic form in the app to request for additional credits. Customer service will receive an email regarding the request. Credits would be manually updated for Customer A (in DB). If Customer A doesn't re-login (where the get request for member is done), localStorage will still show the old no. of credits.
If this is the situation, what's the best way to go about it?
Don't store member data in localStorage at all so as to keep the data fresh. Just call the endpoint whenever it's needed.
Use sessionStorage instead?
Trigger a refetch when the user refreshes the page / app (although user may not know that they need to do this to update the data).
Suggestions?
Calling the endpoint whenever its needed is ideal if the data is going to change based on things outside of the user's control.
Session Storage is just local storage that gets wiped when the browsing session ends, you'll still have the exact same issue
This doesn't really solve the problem, and it's typically a bad user experience to require the user to perform regular maintenance tasks in order to use your application to the best of its ability
I'd go with just getting the data fresh.
At a high level, you have two choices:
Poll (periodically call the back end to refresh the data)
Open a persistent connection (like a web socket) to the server, and have the server push updates to clients.
The latter option would require a lot of changes, and it changes the scalability of your app, so the former choice seems like the most reasonable option for you.
It's smart to keep using localStorage so you have an offline copy of the data and aren't blocking rendering during page load; you can have a background periodic refresh process that doesn't disrupt the user in the meantime. If your data is mirrored in something like redux or context, then your UI could seemlessly update if/when the data changes.
If you do not know when member has been updated, don't store it. You should query the back end every time you need member. That is the only way to keep the data sync with your database.

Can I instantly print information to the database when sessions close when the user closes the browser?

I have a project that I am developing with php. When users log off, the query runs on the MYSQL database, for example: status = 'offline'. But I also want to do this when the user closes the browser. For example, I want to update the query in the MYSQL database instantly when the user is disconnected from the server when the user's computer suddenly shuts down, such as status = 'offline'. To illustrate this, you're texting someone via facebook. The other person's computer suddenly shuts down and, after 1 minute, he is writing offline at the top of the conversation. I want to do something like this, I've tried various methods but failed. I'm new to PHP, can you help me in detail?
A possible solution maybe to update some field in DB saving the most recent user's activity time. It can be done simply by updating this field on every request from client.
Than you can consider user as "offline" in case of not receiving updates within X minutes since the last update.
You can also add some client side code which will send background "keep alive" requests once in a while to inform server that client is still there.

Proper way to detect user's leaving page

I am building a WebApp (ERP) and I need to display the people currently logged in and active on the page. I managed to get something pretty accurate by listening on the mouse/keyboard events and periodically reporting to the DB.
I don't know how to mark people offline when they close the page. I tried using onbeforeunload, but it obviously fires when the user simply changes pages (click a link inside the ERP, that point to another page in the ERP).
I then tried to use WebSockets, but the problem is the same : everytime the page is realoded, the WebSockets connection is closed.
So I can think of two ways:
Use WebSockets indeed, and replace all links by a call to a javascript function that would somehow tell the server that the user is going to change page (so that the server doesn't mark it as offline). But that doesn't feel right, semantically speaking, links should be links, it simply points to another location.
Use either WebSockets or AJAX and never actually change page: links are replaces by a function that will call for the content, and display it on screen (updating the DOM with Javascript). But again, it doesn't feel right either, because semantically speaking the page would have no meaning and the URL would never change, so the user can't "copy paste" the link of the page to refer to it, right ?
So, is there a proper, clean way of doing this? Thanks for your help.
If each of your pages has a webSocket connection to your server, then on the server you can see when any given page is closed by seeing that the webSocket gets closed.
To avoid thinking that a user has left the site when they are just navigating from one page in your site to another, you simply need to add a delay server-side so that you only report that the user has left your site if there has been no webSocket connection from this user for some time period (probably at least a few seconds).
So, on your server when you detect that the last webSocket connection for this user has been closed, you set a timer for some number of seconds. If the user opens up another page on your site (either via navigation or just opens another page) before the timer goes off, you cancel the timer and count the user as still connected. If the timer goes off, then you now know that the user has been away from your site for whatever time period you picked (say 10 seconds) and to you, this will signify that they have left the site. You can control how long you want that time period to be before you decide that, yes they are gone.
All attempts at trying to "see" the user leaving your page IN the browser with Javascript are going to have holes in them because there are always ways for a web page to get closed without your client-side javascript having a chance to tell your server. The beauty of the webSocket solution is that the browser automatically and reliably tells your server when the page is now gone because it closes the webSocket and your server receives the notification that the socket has been closed.
As I understand you want to compute users active on website/pages.
Identify the user (99% unique id computed):
http://valve.github.io/blog/2013/07/14/anonymous-browser-fingerprinting/ you can use another library, there are few.
On each page send from time to time at page load meaning user is navigating or (60sec you can chose lower time frame meaning user is staing on the page) computed id (fingerprint js) to server (web-socket/ajax)
On server you need to have list of id's with expiration date (60s) increment when new user log's in (stored in database or session).
Retrieve on your website the count (60sec ajax/websocket) of id's having timestamp <= server time - let say 120sec.
Knowing if user is logged, and specify the page:
use an object to be sent at server {fingerprint: 123123124234, logged : true, page: home}
Clear your list if you are not storing in Database the users:
Separate thread (server only) access the object and destroy all nodes older then 10 min or whatever your page session is set.
js timer: http://www.w3schools.com/jsref/met_win_setinterval.asp
Let hope it's helpful, id did something similar using the timer at 5 min to sent to server if user is still on the page, or signal at page load.
Getting the cont of users in frame of 60 sec. And even the users with names present on page :)
Somebody already post this kind of question.
Hope this could help you .
Detect if user has closed ALL windows for a website?

AngularJS - Cookies & Cookiestore

I'm making a game and I want to use cookies to save the player's progress. I read the basics on how to use cookies and cookiestore, but I'm having trouble to get started using it.
After some tests I noticed that the game keeps the data if the user refreshes the page, but if he closes the browser, the data is gone. Any methods to save data even if the user closes the browser?
Another thing is that I need to check if the player already has saved cookies or if it's the first time he is playing, so I can retrieve the cookies or set the initial values for the variables.
I don't have any code with the cookies to show yet, but what I'm trying to do, regarding saving, is the same as happens on this game: http://orteil.dashnet.org/cookieclicker/
Thank you in advance.

Categories

Resources