I've got a method that's called by SignalR on multiple tabs when a message is received, but I only want one of these to play an alert sound. My idea was for the first tab to receive it will check if it exists, and if not store a guid relating to that in Localstorage. But I can't understand if I'm going to get synchronous issues with this solution
Yes that should be possible, but you need to be careful, as there is a race condition. You will probably need to call localStorage.getItem, then localStorage.setItem quickly afterwards - but there's no guarantee that another tab hasn't also called setItem in that time.
To work around this, look for some sort of mutex that can be used with localStorage. I have previously written my own, but you could use:
https://github.com/chieffancypants/fast-mutex
Related
I've been building data driven applications for about 18 years and for the past two, I've been successfuly using angular for my large forms/crud based apps. You know, the classic sql server db with hundreds of tables with millons of records. So far, so good.
Now I'm porting/re-engineering a desktop app with about 50 forms, all complex, all fully functional, "smart". My approach for the last couple years was to simply work tightly with the backend rest API to retrieve, insert or update data as needed and everything works fine.
Then I stumbled across ngrx and I understand exactly how it works, what it does and why it is good for a "reactive" app.
My problem is the following: In the usual lifecycle of the kind of systems i mentioned, you always have to deal with fresh data and always have to tell everything to the server. Almost no data in such apps can be safely "stored" localy since transactional systems rely on centralized data interactions. There's no such thing as "hey lets keep this employee's sales here for later use".
So why would it be so important to manage a local 'store' when most of my data is volatile? I understand why it would be useful for global app data like user-profile or general ui related state, but for the core data itself? I dont get it. You query for data, plug that data in the form, it gets processed by the user and sent back to the server. That data is no longer needed, and if you do need it, you ask for it again, as it could have changed its state since the last time you interacted with it.
I do not understand the great lengths i have to go to mantain a local store and all the boilerplate if that state is so volatile.
They say change detection does not scale but I've build some really large web apps with a simple "http service" pattern and it works just fine, cause most of the component-tree is destroyed anyway as you go somewhere else in the app, and any previous subscriptions become useless. Even with large-bulky-kinky forms, it's never that big of a problem the inner workings of a form as to require external "aid" fro a store. The way I see it, the "state" of a form is a concern of that form in that moment alone. Is it to keep the component tree in sync? never had problems with that before... even for complicated trees with lots of shared data, master detail is kind of a flat pattern in the end if al lthe data is there.
For other components, such as grids, charts, reporte, etc, same thing applyes. They get the data they need and then "puf", gone.
So now you see my mindset. I AM trying to change it to something better. Why am I missing out the redux pattern?
I have a bit of experience here! It's all subjective, so what I've done may not suit you. My system is a complex system that sounds like it's on a similar scale as yours. I battled at first with the same issues of "why build complex logic on the front end and back end", and "why bother keeping stuff in state".
A redux/NGRX approach works for me because there are multiple ways data can be changed - perhaps it's a single user using the front end, perhaps it's another user making a change and I want to respond to that change straight away to avoid concurrency issues down the track. Perhaps there are multiple parts within my front end that can manipulate the same data.
At the back end, I use a CQRS pattern instead of a traditional REST API. Typically, one might suggest to re-implement the commands/queries to "reduce" changes to the state, however I opted for a different approach. I don't just want to send a big object graph back to the server and have it blindly insert, and I don't want to re-implement logic on the client and server.
My basic "use case" life cycle looks a bit like:
Load a list of data (limited size, not all attributes).
User selects item from list
Client requests "full" object/view/dto from server
Client stores response in object entity state
User starts modifying data
These changes are stored as "in progress" changes in a different part of state. The system is now responding to the data in the "in progress" part
If another change comes in from server, it doesn't overwrite the "in progress" data, but it does replace what is in the object entity state.
If required, UI shows that the underlying data has changed / is different to what user has entered / whatever.
User clicks on the "perform action" button, or otherwise triggers a command to be sent to server
server performs command. Any errors are returned, or success
server notifies client that change was successful, the client clears the "in progress" information
server notifies client that Entity X has been updated, client re-requests entity X and puts it into the object entity state. This notification is sent to all connected clients, so they can all behave appropriately.
I'm creating an indicator which notifies the user about whether or not the local state is in sync with the latest fetched server state. I can think of several ways to keep track of this:
storing an additional 'pristine' state next to the normal 'soiled' state upon fetching data and diffing those states in my indicator component
toggling a up-to-date-flag upon state changes and fetching data back and forth
But those solutions seem over-engineered and error-prone to me. I think middleware is probably the cleanest solution here, but thusfar I haven't came across a viable out-of-the-box solution. If anyone could hook me up, because I probably lack the right idiom to use in my search terms, that would be awesome. On a sidenote: I'm not allowed to store my data in the localstorage.
I would recommend calculating a hash (this works as the signature of your state) of your data on the server, and sending it along with your data to local clients. Your clients can then use this hash to know if it matches with the latest data.
You might also want to take a look at Etag for a more standardized approach.
https://en.wikipedia.org/wiki/HTTP_ETag
I'm starting to read up on Redux and I like what I see so far. There is one area of concern that I have and it's async actions. I've seen how sagas, thunk, and others help in this area but I feel like I'm missing something.
I'm a fan of using FSMs to handle application logic and prevent things from getting out of sync, so coming to redux and not seeing something like this is a bit jarring to me.
I have an example in my mind that I keep coming back to that I want redux (or some plugin) to solve:
I have a login form. When the user presses login, an async call is made to a server. This is fine. But if the user presses login again, then another call is made to the server and the application state is now out of sync. I could add a state property that defines loggingIn, but this only works in this example.
Lets say I have a much bigger dependency. Lets say when a user logs in, an action is done to preload some data. And that data contains a preflight of more data to load. This now introduces a lot of if/else conditional logic and adds more information to the state. In a FSM, I would define multiple concurrent states for theses. Such as user:loggedIn, manifest:fetched, pageData:fetched. And each state would be a child of each other: user:loggedIn -> manifest:fetched -> pageData:fetched. So if a request was made to login, or refetch data, an error would be thrown because it's not a valid handler for the current state. How does one accomplish such complexity in Redux? Is it even possible?
Another example. Stemming off the Reddit API example. Lets say a user goes to a reddit post. I don't want the user to be able to submit a comment on the post before it's even loaded. I know this could be handled on the UI side with conditionals and such, but that seems really archaic.
I really appreciate any guidance.
Thanks!
I want to write a web app order system using the REST methodology for the first time. I understand the concept of the "message id" when things get posted to a page but this scenario comes up. Once a user posts to the web app, you can keep track of their state with an id attached to the URI but what happens if they hit the back button of the browser to the entry point of the app when they didn't have any id? They then lose their state in the transaction.
I know you can always give them a cookie but you can't do that if they have cookies turned off and, worst case thinking here, they also have javascript turned off.
Now, I understand the answer may be "Yes, that's what will happen", that's the end of the story, and I can live with that but, being new to this, is there something I'm missing?
REST doesn't really have states server-side; you simply point to resources. User sessions aren't tracked; instead cookies are used to track application state. However, if you find that you really do need session state, then you are going to have to break REST and track it on the server.
A few things to consider:
How many of your users have cookies disabled anyway? How many even know how to do that?
Is it really likely that your users will have JS turned off? If so, how will you accomplish PUT (edit) and DELETE (delete) without AJAX?
EDIT: Since you do not want to force cookies and JavaScript, then you cannot have a truly RESTful system. But you can somewhat fake it. You are going to need to track a user server-side. You could do this with a session object, as found in your language/framework of choice or by adding a field to the database for whatever you want to know. Of course, when the user hits the back button, they will likely be going to a cached page. If that's not OK, then you will need to modify the headers to disallow caching. Basically, it gets more complicated if you don't use cookies, but not unmanageable.
What about the missing PUT and DELETE HTTP methods? You can fake those with POSTs and a hidden parameter specifying whether or not you are making something new, editing something, or deleting a record. The GET shouldn't really change.
The answer is that your application (in a REST scenario) simply doesn't keep track of what happens. All state is managed by the client, and state transitions are effected through URI navigation. The "State Transfer" part of REST refers to client navigation to new URIs which are new states.
A URI accessed with GET is effectively a read-only operation as per both the HTTP spec and the REST methodology. That means if the client "backs up" to some previous URI, "the worst" that happens is another GET is made and more data is loaded.
Let's say the client does this (using highly simplified pseudo-HTTP)...
GET //site.com/product/123
This retrieves information (or maybe a page) about product ID 123, which presumably includes a reference to a URI which can be used to POST that item into the user's shopping cart. So the user decides to buy the item. Again, it's oversimplified but:
POST //site.com/shoppingcart/
{productid = 123}
The return from this might be a representation of the shopping cart, or a reference to the added item (which could be used on the shoppingcart URI with DELETE to remove the item again), or a variety of other things (such as deeper XML describing the cart contents with other URIs pointing to the cart items and back to the original products). It's all up to you.
But the "state" is defined by whatever the client is doing. It isn't tracked on the server at all, although you will certainly keep a copy of his shopping cart contents in your database for some period of time. (I once returned to a website two years later and my shopping cart items were still there...) But it's up to him to keep track of the ID. To your server app it's just another record, presumably with some kind of expiration.
In this way you don't need cookies, and javascript is entirely dependent on the client implementation. It's difficult to build a decent REST client without script -- you could probably build something with XSLT and only return XML from the server, but that's probably more pain than anyone needs.
The starting point is to really understand REST, then design the system, then build it. It definitely doesn't lend itself to building it on the fly like most other systems do (right or wrong).
This is an excellent article that gives you a fairly "pure" look at REST without getting too abstract and without bogging you down with code:
http://www.infoq.com/articles/subbu-allamaraju-rest
It is true that the "S" in REST stands for "state" and the "T" for "transfer". But the state is is kept on the client, not on the server. The client always hast all information necessary to decide for himself in whicht direction he wants to change the state.
The way you describe it, your system is not restful.
I guess it's quite a common problem in databinding scenarios.
What do you usually do, if you are running a batch update and want to avoid that a propertychanged-dependend calculations/actions/whatever are executed for every single update?
The first thing which usually comes to my mind, is to either introduces a new boolean or unhook/hook the eventhandler, ...
What I don't like about this approaches is:
they introduce new complexity (has to be maintained, ...)
they are error prone, because you have to make sure that a suppressed notifications are sent afterwards
I'm wondering if somebody addressed this problem already in a more convenient way that is more easy to handle?
tia
Martin
Edit: not to missunderstand me. I know about the things .NET provides like RaiseListChangedEvents from BindingList, ... They are all addressing the problem in more/less the same way as I described, but I'm searching for a different way which doesn't have to listed drawbacks.
Maybe I'm on the wrong track, but I though I give it a try here...
There isn't a single one-size-fits-all solution, unfortunately. I've applied or seen the following solutions:
There are two singals. One signal is emitted when the change comes from a user action, the other always fires. This allows to distinguish between changes in the UI and updates by code.
A boolean to protect code
The property event framework stops propagating events automatically when a value didn't really change.
A freeze/thaw method on the signal or the signal manager (i.e. the whole framework)
A way to merge signals into a single one. You can do N updates and they get collected into M signals where M <= N. If you change the same property 100 times, you still only get 1 signal.
Queuing of signals (instead of synchronous execution). The queuing code can then merge signals, too. I've used this with great success in an application that doesn't have a "Save" button. All changes are saved to the database as you make them. When you change a text, the changes are merged over a certain time (namely until the previous DB update returns) and then, they are committed as a single change.
An API to set several values at once; only a single signal is emitted.
The signal framework can send signals at different levels of granularity. Say you have a person with a name. When you change the name, you get two signals: One for the name change and one "instance field changed". So if you only care "has something changed", then you can hook into the instance instead of all the fields.
What platform? The post makes me think .NET.
What is the underlying objects? For example, BindingList<T> as a source allows you to disable notifications by setting RaiseListChangedEvents to false while doing the update.
Other than that (or similar); yes, disconnect the binding during big updates
The easiest route to take is to use the BindingSource component for your data binding. Instead of binding your controls to a particular object (or IList), use that object as the DataSource for the BindingSource, then bind the controls to the BindingSource.
The BindingSource class has SuspendBinding() and ResumeBinding() functions.