Potentially "subjective" question : what is a sweet spot for introducing reactive programming (rxjs, bacon, etc...) into an existing, "old-school- MVC-jquery" client side application ?
For example, Promises shine the most if you introduce it in the "API calls" layer of an application (and you can do it one function at a time, returning a Promise instead of accepting a callback - they, it tends to disseminate once everyone in the team gets a few benefits.)
From most of the tutorials I could read, I do not really see where rxjs would shine most. In the widgets (returning stream of events instead of having a 'listener-based' API ?)
Any experience welcome.
It is hard to say where it will shine the most…
For me, the key feature, is that it allows to describe code in more declarative way instead of writing complicated state machines(as it often happens when working with async logic).
In general, it can be quite useful for anything async for example in UI, or for API calls layer implementation as you mentioned about Promises, but better(promise is just a limited version of observable, except the fact that observable is lazy).
In case of implementing API calls layer, in comparison to promises it will have at least following benefits:
subscription to observable is cancellable(disposable) - for example, you can switch between subscriptions for api results without worrying about race conditions with previous api requests... it is as simple as results = queries.switchMap(q=>doApiCall(q))
it can return multiple values using the same interface - you can easily replace ajax call with subscription to web-socket, and you will not need to change code that is using this.
better error handing - it is quite easy with rx to do things like retrying operation n-times before throwing an error, or handling timeout.
I suggest you to watch Netflix JavaScript Talks - Async JavaScript with Reactive Extensions by Jafar Husain, there is great examples about where RxJS can be helpful. And likely it would be mostly an answer to your question.
Related
If a Future displays a once off piece of data while a Stream offers the additional advantage of updating information in real-time when data is modified at the source (ie, Firestore database), then why would one ever use a Future? What disadvantages would using a Stream over a Future have?
Why would one ever use a Future?
A Future handles a single event when an asynchronous operation completes or fails. It can be used for simple HTTP requests (GET, POST, ...).
You can have a look to the boring flutter development show where Google engineers build a simple Hacker News app, with Futures.
EDIT
New video from Flutter team about dart Futures
What disadvantages would using a Stream over a Future have?
They are made for different needs : real time updates or asynchronous calls, so they cannot really be compared in terms of advantages of one over the other.
There are many articles out there that recommend using ngrx/effects for handling async actions such as http REST calls. Instead of using effects, why can't we just use a regular service to make the http call and then take the result of that http call and dispatch an action? Doesn't that simplify things?
You can perfectly use a regular service and then dispatch an action, like this on a component.
this.store.dispatch({
type: "SAVE_DATA",
payload: data
});
this.saveData(data) // POST request to server
.map(res => this.store.dispatch({type: "DATA_SAVED"}))
.subscribe()
#ngrx/effect just abstracts this logic away from the component. By doing this with a functional programmic aproach (pure functions), code remains very easy to test.
I really recommend reading this article, since there are many solutions to problems that abuse effects
Post
Using ngrx/effects makes life more simpler than using service to make http call and then take the result and dispatch the action. As following
Effects provide abstraction to the service layer. Our components don't need to know about the services(http) layer. Components will only dispatch actions to get things done.
As Effects are basically service, code is written once and reused multiple times.
In the everyday front-end development I often use DOM as a global event bus that is accessible to every part of my client-side application.
But there is one "feature" in it, that can be considered harmful, in my opinion: any listener can prevent propagation of an event emitted via this "bus".
So, I'm wondering, when this feature can be helpful. Is it wise to allow one listener to "disable" all the other? What if that listener does not have all information needed to make right decision about such action?
Upd
This is not a question about "what is bubbling and capturing", or "how Event.stopPropagation actually works".
This is question about "Is this good solution, to allow any subscriber to affect an event flow"?
We need (I am talking about current usage in JS) stopPropagation() when we want to prevent listeners to interfere with each other. However, it is not mandatory to do so.
Actual reasons to avoid stopPropagation:
Using it usually means that you are aware of code waiting for the same event, and interfering with what the current listener does. If it is the case, then there may (see below) be a design problem here. We try to avoid managing a single thing at multiple different places.
There may be other listeners waiting for the same type of event, while not interfering with what the current listener does. In this case, stopPropagation() may become a problem.
But let's say that you put a magic listener on a container-element, fired on every click to perform some magic. The magic listener only knows about magic, not about the document (at least not before its magic). It does one thing. In this case, it is a good design choice to leave it knowing only magic.
If one day you need to prevent clicks in a particular zone from firing this magic, as it is bad to expose document-specific distinctions to the magic listener, then it is wise to prevent propagation elsewhere.
An even better solution though might be (I think) to have a single listener which decides if it needs to call the magic function or not, instead of the magic function being a stoppable listener. This way you keep a clean logic while exposing nothing.
To provide (I am talking about API design) a way for subscribers to affect the flow is not wrong; it depends on the needs behing this feature. It might be useful to the developers using it. For example, stopPropagation has been (and is) quite useful for lots of people.
Some systems implement a continueX method instead of stopX. In JavaScript, it is very useful when the callees may perform some asynchronous processing like an AJA* request. However, it is not appliable to the DOM, as the DOM needs results in time. I see stopPropagation as a clever design choice for the DOM API.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I have been using RxJava in my project for about a year now.
With time, I grew to love it very much - now I'm thinking maybe too much...
Most methods I write now have some form of Rx in it, which is great! (until it's not).
I now notice that some methods require a lot of work to combine the different observable producing methods.
I get the feeling that although I understand what I write now, the next programmer will have a really hard time understanding my code.
Before I get to the bottom line let me give an example straight from my code in Kotlin (Don't dive too deep into it):
private fun <T : Entity> getCachedEntities(
getManyFunc: () -> Observable<Timestamped<List<T>>>,
getFromNetwork: () -> Observable<ListResult<T>>,
getFunc: (String) -> Observable<Timestamped<T>>,
insertFunc: (T) -> Unit,
updateFunc: (T) -> Unit,
deleteFunc: (String) -> Unit)
= concat(
getManyFunc().filter { isNew(it.timestampMillis) }
.map { ListResult(it.value, "") },
getFromNetwork().doOnNext {
syncWithStorage(it.entities, getFunc, insertFunc, updateFunc, deleteFunc)
}).first()
.onErrorResumeNext { e -> // If a network error occurred, return the cached data and the error
concat(getManyFunc().map { ListResult(it.value, "") }, error(e))
}
Briefly what this does is:
Retrieve some timestamped data from storage
If data is not new, fetch data from network
Sync network data again with the storage (to update it)
If a network error occured, again retrieve the older data and the error
And here comes my actual question:
Reactive programming offers some really powerful concepts. But as we know with great power comes great responsibility.
Where do we draw the line? Is it OK to fill our entire programs with awesome reactive oneliners or should we save it only for really mundane operations?
Obviously this is very subjective, but I hope someone with more experience can share his knowledge and pitfalls.
Let me phrase it better
How do I design my code to be reactive yet easy to read?
When you pick up Rx, it becomes this awesome shiny hammer and everything starts looking like a rusty nail just waiting for you to bang in.
Personally, I think the biggest clue is in the name, reactive framework. Given a requirement, you need to reflect upon whether a reactive solution truly makes sense.
In any Rx proposition, you are looking to introduce one or more event streams and carry out some action in response to an event.
I think there are two key questions to ask:
Are you in control of the event stream?
To what degree must you complete responses at the rate of the event stream?
If you do not have control of the event stream and you must respond at the rate of the event stream then Rx is a good candidate.
In any other circumstance, it is probably a poor choice.
I have seen many examples where people have jumped through hoops to create the illusion of a lack of control in order to justify Rx - which seems crazy to me. Why give up the control that you have?
Some examples:
You have to extract data from a fixed list of files and store it in a database. You decide to push each file name into a subject and create a reactive pipeline that opens each file and projects the data, then processes the data in some way and finally writes it to the database.
This fails the control test and the rate test. It would be far easier to iterate over the files and pull them in and process them as fast as you can. The phrase "decide to push" is the giveaway here.
You need to display stock prices from a stock exchange.
Clearly this is a good choice for Rx. If you can't keep up with the rate of prices in general, you are screwed. It might be the case that you conflate prices (perhaps to provide an update only once every second) - but this still qualifies as keeping up. The one thing you can't do is ask the stock exchange to slow down.
These (real world) examples pretty much fall at opposite ends of the spectrum and don't have much grey area. But there is a lot of grey area out there where control isn't clear.
Sometimes you are wearing the client hat in a client/server system and it can be easy to fall into the trap of sacrificing control, or putting control in the wrong place - which can easily be fixed with correct design. Consider this:
A client application displays news updates from a server.
News updates are submitted to the server at any time and are created in high volume.
The client should be refreshed at an interval set by the client.
Refresh interval can be changed at any time and the user can always request an immediate refresh.
The client only shows updates tagged with particular keywords, as specified by the user.
The news updates are sometimes lengthy and the client should not store the full content of news updates, but rather display the headline and summary.
At user request, the full content of an article can be shown.
Here, the frequency of news updates is not in control of the client. But the desired refresh rate and the tags of interest are.
For the client to receive all the news updates as they arrive and filter them client side isn't going to work. But there are plenty of options:
Should the server send a data stream of updates taking into account the client refresh rate? What if the client goes offline?
What if there are thousands of clients? What if the client wants an immediate refresh?
There are lots of valid ways to tackle this problem that include more or less reactive elements. But any good solution should take account of the client's control of tags and desired refresh rate, and the lack of control of news update frequency (by client or server). You might want the server to react to changes in client interest by updating the events that it pushes to the client - which it pushes only as long as the client is listening (detected via a heartbeat). When the user wants a full article, then the client would pull the article down.
There is much debate in the Rx community about back-pressure. This is the idea that the client should inform the server when it is overloaded and the server respond by somehow reducing the event stream. I think this is a misguided approach that can lead to confusing designs.
To my mind, as soon as a client needs to give this feedback, it has failed the response rate test. At this point, you are not in a reactive situation, you are in an async enumerable situation. i.e. The client should be saying "I am ready" when it is ready for more and then waiting in a non-blocking fashion for server to respond.
This would be appropriate if the first scenario were modified to be files arriving in a drop-folder, of varying lengths and complexity to process. The client should make a non-blocking call for the next file, process it, and repeat. (Add parallelism as required) - and not be responding to a stream of file-arrived events.
Wrap up
I've deliberately avoided other valid concerns such as maintainability of code, performance of Rx itself etc. Most because they are addressed elsewhere and more importantly because I think the ideas here are more divisive than those concerns.
So if you reflect on the elements of control and response rate in your scenario you and will probably stay on the right track.
The response rate issue can be subtle - and the degree aspect is important. Arrival rate can fluctuate, and there is going to be some acceptable degree of fluctuation in response rate - clearly, if you don't ultimately have a way to "catch up" then at some point the client will blow up.
I find that there are two things I keep in mind when writing Rx (or any mildly sophisticated/new technology)
Can I test it?
Can I easily hire someone that can maintain it. Not struggle to maintain it, but will be fine left alone to maintain it?
To this end, I also find that just because you can, doesn't always mean you should. As a guide I try to avoid creating queries that are over say 7 lines of code. Queries bigger than this, I try to separate into sub queries that I compose.
If code you have provided is at the core of the code base, and is at the extreme end of the complexity, then It may be fine. However, if you find all of your Rx code carries that much complexity, you may be creating a difficult to work with code base.
i have a rather general question: How to call a method in RESTful web service correctly?
The method is supposed to do only a transformation in the database and return nothing (so no GET?!). However I also send no values from the client (so no PUT/POST?!?).
So far I am using GET. Put i read thats not the proper way to do it...
Thanks in advance!
REST stands for "REpresentational State Transfer". If you're not transferring state representing the thing you're working with (in one direction or the other), it's pretty much inherently not RESTful, and there's no correct way of doing it and still calling it REST.
If you want RPC, then do RPC. Just don't call it RESTful. :)
The way you do it is through RPC. REST is good for state transfer, but not for triggering actions that have nothing to do with state transfer, such as operations that affect a large number of records. Most systems I've seen use REST for 99% of the work in supporting a UI, and RPC for that last 1% -- operations that do not involve state transfer, bulk update operations, that sort of thing. Your goal should be to express as much of the business logic as possible as reaction to application of state, reserving the corner cases for RPC.
There's really no "correct" way to do this if you're not transfering any kind of data. You're simply calling a method, so REST does not really apply.
These days PATCH with a "JSON Patch" payload might be a way to go - but it's STILL not RESTful.
Calling it an RPC is more appropriate and no reason it cannot be in the same API as long as it is documented. Document your API with your RPC methods and REST resources separated.
E.g.
See:Understanding RPC vs REST For HTTP APIs