I'm trying to build application (to be more accurate a library for my personal projects) which will be based on room management (lobby, matchmaking, rooms, etc).
I managed to do it with socket.io.
Now, my question is, I don't know what kind of design pattern should I use.
I noticed that socket.io has ack callbacks, which surprised me and think it's good, but I'm not sure what's the difference between sending back ack with parameters or emitting an event with parameters.
So, question is, what's the pros and cons using acks over emitting an event and vice-versa?
Let's say, what's the pros and cons using following codes:
assuming handler callback is fn(err, res);
acknowledgement style:
socket.on('join', function (data, ack) {
// do the joining stuff here.
return ack(null, { response: 'goes_here' });
});
versus
event emitting style:
socket.on('join', function (data, ack) {
// do the joining stuff here.
io.to(client_sid).emit('join_response', null, { response: 'goes_here' });
});
As you noted, there is not a real difference if you only think about the ping-pong thing. I would the notable changes is that it allows you to validate a specific event has been acknowledged (although you could argue that you can also do that with a _response event by passing an event id), and provides a more convenient way to handle responses, by using a simple callback style notation: the first example looks way cleaner and simple.
Besides, it allows you to avoid creating two event keys for just one type of event which is kinda repeating. Acknowledgement has been made for this purpose, so there is no real reason not to use it in favor or creating another event.
Related
I noticed that when I unsubscribe from query, http request is still executing and not being canceled. Also tried to use AbortController but without any luck. How does one cancel http requests made by Apollo client?
This is an old question, but since I just wanted to do the same and managed to do it with the latest Apollo Client (3.4.13) and Apollo-Angular (2.6.0), you need to make sure that you're using watchQuery() instead of query(), and then call unsubscribe() on the returned Apollo subscription from the previous request. The latter implies of course that you should store somewhere the subscription object that you want to abort.
This is an old question, but I spent two days on this bananas problem and I want to share for posterity.
We're using Angular and GraphQL (apollo-angular and codegen to make GraphQL services) and we opted for an event-driven architecture using NgRx to send events and then perform http calls. When sending multiple identical events (but with different property values) we noticed we got stale data in some cases, especially edge cases like when 20+ of these identical events were sent. Obviously not common, but not ideal, and a hint of perhaps bad scale since we were going to need many more events in future.
The way we resolved this issue was by using .watch() instead of .fetch() on the GraphQL generated services. Initially, since .fetch() returned the same Observable as .watch().valueChanges, we thought it was easier and simpler to just use .fetch(), but their behavior seems much different. We were never able to cancel http requests performed by .fetch(). But after changing to .watch().valueChanges, the Observable acted exactly as http request Observables would, complete with -- thankfully -- cancelation.
So in NgRx, we swapped our generic mergeMap operator for the switchMap operator. This will ensure previous effects listening on dispatched events will be canceled. We needed no extra overhead, no .next-ing to Subjects, no extra Subscriptions. Just change .fetch() into .watch().valueChanges and then switchMap to your heart's content. The takeUntil operator will now also cancel these requests, which is our performed method of unsubscribing from Observables.
Sidenote: I'm amazed that this information was this hard to come by, and honestly this question and one GitHub issue was all I could find to intimate this discrepancy. Even now I don't quite understand why anyone would want .fetch() if all it does is perform an http call that will always resolve and then return an Observable that does not behave the way you expect Observables to behave.
I am looking for a pub/sub mechanism that behaves like a promise but can resolve multiple times, and behaves like an event except if you subscribe after a notification has happened it triggers with the most recent value.
I am aware of notify, but deferred.notify is order-sensitive, so in that way it behaves just like an event. eg:
d.notify('notify before'); // Not observed :(
d.promise.progress(function(data){ console.log(data) });
d.notify('notify after'); // Observed
setTimeout(function(){ d.notify('notify much later') }, 100); // Also Observed
fiddle: http://jsfiddle.net/foLhag3b/
The notification system I'd like is a good fit for a UI component that should update to reflect the state of the data behind it. In these cases, you don't want to care about whether the data has arrived yet or not, and you want updates when they come in.
Maybe this is similar to Immediate mode UIs, but is distinct because it is message based.
The state of the art for message based UI updating, as far as I'm aware, is something which uses a promise or callback to initialize, then also binds an update event:
myUIComponent.gotData(model.data);
model.onUpdate(myUIComponent.gotData); // doing two things is 2x teh workz :(
I don't want to have to do both. I don't think anyone should have to, the use case is common enough to abstract.
model.whenever(myUIComponent.gotData); // yay one intention === one line of code
I could build a mechanism to do what I want, but I wanted to see if a pub/sub mechanism like this already exists. A lot of smart people have done a lot in CS and I figure this concept must exist, I just am looking for the name of it.
To be clear, I'm not looking to change an entire framework, say to Angular or React. I'm looking only for a pub/sub mechanism. Preferably an implementation of a known concept with a snazzy name like notifr or lemme-kno or touch-base.
You'll want to have a look at (functional) reactive programming. The concept you are looking for is known as a Behavior or Signal in FRP. It models the change of a value over time, and can be inspected at any time (continuously holds a value, in contrast to a stream that discretely fires events).
var ui = state.map(render); // whenever state updates, so does ui with render() result
Some popular libraries in JS are Bacon and Rx, which use their own terminology however: you'll find properties and observables.
I've been using Dojo in various contexts and never found a good explanation on events versus topics. What I understand from using both mechanisms is the following:
Both are event or more generally message mechanisms.
Both work more or less the same, in that you subscribe to a topic/event by setting a callback.
Events are tightly coupled to an object/widget, as in, you need the actual instance of an object or widget to register listeners for specific events.
The topic mechanism on the other hand provides a more decoupled approach, as you can subscribe for any topic without knowing which component is publishing the topic, or even without knowing if the topic will be published at all.
An approach I used a couple of times when developing custom widgets with Dojo was by letting them publish to certain topics. Other components would subscribe to these topics and react appropriately. However, this leads to code that is hard to follow, because when you find a piece of code that subscribes to a certain topic, you start wondering who is publishing to that topic and vice versa. Currently I tend to let my custom widgets submit events and have a controller listening to these events and dispatch them to other widgets that should react on these events.
So in the first approach, the topic mechanism is the glue between widgets, but it is decentralized which makes it hard to maintain the code on the longer term in my experience. In the second approach, a controller class (following the MVC pattern) is the glue, which centralizes event handling.
I'd be interested in knowing if this is a correct understanding of the two mechanisms. I'd also be interested in any design consideration one should take in account when choosing one of the two (or mix them even?). Any pointers to an elaborate discussion on the topic would be appreciated as well. I have been looking at: http://dojotoolkit.org/documentation/tutorials/1.9/events/ but that mainly describes how both mechanisms work but give little insight in how to structure a complex application.
I'm having the exact same idea about topics and events as you. As JavaScript is event-driven both are of course event-ish (like you describe in your first point).
Events are indeed coupled to the widget itself while topics aren't. I usually see it as the following:
When you have master-slave kind of structure (like a list having many items), then using widgets and events is probably the best approach to handle your problem.
When both widgets are unrelated to each other, then topics are probably the best way to communicate between each other.
You're right, topics make it harder to know what the origin is, but if you think about it, you don't need to know the origin. The topics provide you an API that decouples the source from the destination, making it so that you don't need to know the source.
Because both widgets are unrelated (that's the approach I follow, described before), you should normally don't need to know what the origin is when maintaining the code.
What you need is a well written API and make sure both source as destination are following it. If the API changes (code maintaining) you can use your IDE to find out which widgets are publishing/subscribing (for example by searching to the topic name) and make sure each of them is updated.
You can also choose to encapsulate the publish/subscribe behavior and providing a more high level API by creating a module like this:
define([ "dojo/topic", "dojo/_base/array" ], function(topic, arrayUtils) {
var MY_TOPIC = "/my/topic";
var module = {
observers: [],
notify: function(/** String */ name, /** Integer */ age) {
topic.publish(MY_TOPIC, {
name: name,
age: age
});
},
addObserver: function(/** Function */ callback) {
return this.observers.push(callback) - 1;
},
removeObserver: function(/** Integer */ index) {
this.observers[index] = null;
}
};
topic.subscribe(MYTOPIC, function(data) {
arrayUtils.forEach(module.observers, function(observer) {
if(observer !== null && data.name !== undefined && data.age !== undefined) {
observer(name, age);
}
});
});
return module;
});
You publish using the notify() function (providing the correct function parameters) and you add/remove observers with the other functions. Then you will make this component your sole subscriber and make it notify all observers.
This way you don't need to know about the topic and the API is uniform. You only need to make sure that the callbacks use the arguments correctly. To maintain your code you just change the high level API and look for modules that use this high level component. This is way easier to detect since it's in the require() function.
When I use topics I usually create a high level API like this (might change a bit depending on the use of it). But I think the point made is clear, it's easier to change the topic and to modify the data that is sent through.
In the sense of design patterns and software architecture topics seem to be the perfect mechanism to implement flux in dojo. Found an article with basic idea here.
I've been studying event listeners lately and I think I've finally gotten them down. Basically, they are functions that are called on another object's method. My question is, why create an event listener when calling the function will work just fine?
Example, I want to call player.display_health(), and when this is fired, the method player.get_health() should be fired and stored so that display_health() has access to it. Why should I use an event listener over simply calling the function? Even if display_health() were in another object, this still doesn't appear to be a problem to me.
If you have another example that fits the usage better, please let me know. Perhaps particular languages don't benefit from it as much? (Javascript, PHP, ASP?)
You might not always be in control of the code that's doing the calling. Or even if you are, you don't want to introduce dependencies into that code. In cases like that, it's better for the code to fire an event and allow the code you do control, or the code that should have the dependency, to listen for the event and act accordingly.
For example, perhaps you're creating a library that will be used by other people. They don't have the source code or in some way can't/shouldn't be able to modify it (or shouldn't have to). Your documentation states that specific events are raised under specific circumstances. They can then, in turn, respond to those events.
Or perhaps you have some domain libraries in your enterprise. You do control them and can modify them, but architecturally they're generally considered to be working as they currently are coded and shouldn't be changed. (Don't want to incur a round of QA to re-validate the updated code, the code belongs to another department and they don't want you to change it, etc.) And you're in the position where you want that code to be able to do different things in different circumstances/environments. If that code raises and event where relevant, you can hook your code into it (and/or swap out accordingly) without having to mess with that code.
Just a couple quick examples, I'm sure others have more.
My question is, why create an event listener when calling the function will work just fine?
What if you don't know what function you want to call?
Take the classic example, a Button that the user can click on. Whoever writes the library has no idea what function you want called when the button is clicked. It would also be pretty prohibitive if every Button could only call the same function when it is clicked.
So instead, you can attach an event handler to the event. Then when the event is triggered, the Button can do what it needs to, without having to know at compile-time exactly what function it's supposed to be calling.
In Brief, you can write the code without event listener, but using event listener help other to use the same code as library.
Even with the detailed answers above, I was still having trouble understanding what the actual difference was between using a controller / functions OR an event listener.
One of the things that has been left out in all of these answers is that the use of Events and Event Listeners comes in handy when you do not want to couple your code so closely. Each function, class, etc, should have singleness of purpose.
So say you are getting hit with an API request from an outsider. In my case, my exact problem understanding this concept was when I am receiving API calls from Stripe Webhooks.
The purpose of Stripe Webhooks is: say a customer spends $10,000 on your website. Your standard procedure is to Auth and Capture. Update DB to reflect their new membership status. In a perfect world, and in our company's case, 999/1000 times, this goes perfectly. Either their card is declined on the spot, or the payment goes through. In both cases, we send them an email letting them know.
But what about the 1/1000 time when the user pays and Stripe returns a Card Failure error (which can be a number of different things)? In our case, we email them and tell them the billing has failed. The problem we've encountered is that some BANKS are investigating large charges, which comes back as an Error, but then a few minutes later the bank authorizes the charges and the payment is captured.
So what is there to do? Enter Stripe Webhooks. Stripe Webhooks will hit an API endpoint if something like this occurs. Actually, Stripe Webhooks can hit your API any and every time a payment isn't instantly Authed, Captured, or if the customer asks for a refund.
This is where an Event Listener comes in handy. Stripe shoots over a POST with the customer info, as well as the Webhook type. We will now process that, update the database, and shoot them a success email.
But why not just use a standard route and controller?
The reason we don't just use a standard route and controller is because we would either need to modify the already defined functions, classes, etc, or create a new series of classes that are coupled together, such as -> Stripe API Calls Received, Update DB, Send Email. Instead of coupling these closely together, we use an Event Listener to first accept the API Call, then hit each of those Classes, Functions, etc., leaving everything uncoupled.
I looked everywhere, and I think the Laravel documentation explains it best. I finally understood when given a concrete example, and what the purpose of an Event Listener is:
Events serve as a great way to decouple various aspects of your application, since a single event can have multiple listeners that do not depend on each other. For example, you may wish to send a Slack notification to your user each time an order has shipped. Instead of coupling your order processing code to your Slack notification code, you can raise an OrderShipped event, which a listener can receive and transform into a Slack notification.
https://laravel.com/docs/5.6/events
I think the main reason for events vs function calls is that events are 'listened to' while calls are 'made'. So a function call is always made to another object whereas listeners 'choose' to listen for an event to be broadcast from your object.
The observer pattern is a good study for this capability. Here is a brief node.js example which illustrates the concept:
var events = require('events');
var Person = function(pname) {
var name = pname;
};
var james = new Person('james');
var mary = new Person('mary');
var loudmouth = new Person('blabberer');
loudmouth.mouth = new events.EventEmitter();
//jame's observer.
james.read_lips = function(msg){
console.log("james found out: " + msg);
};
//james adds his event to the emitter's event listener.
james.enter_elevator = function(){
console.log('james is in the elevator');
//NOTE: james adds HIMSELF as a listener for the events that may
//transpire while he is in the elevator.
loudmouth.mouth.on('elevator gossip', james.read_lips)
};
//james removes his event from the emitter when he leaves the elevator.
james.leave_elevator = function(){
// read lips is how james responds to the event.
loudmouth.mouth.removeListener('elevator gossip', james.read_lips);
console.log('james has left the elevator');
};
//mary's observer
mary.overhear = function(msg){
console.log("mary heard: " + msg);
};
//mary adds her observer event to the emitter's event listeners
mary.enter_elevator = function(){
// overhear is how mary responds to the event.
console.log('mary is in the elevator');
//NOTE: now mary adds HERSELF to the listeners in the elevator and
//she observes using a different method than james which suits her.
loudmouth.mouth.on('elevator gossip', mary.overhear);
};
loudmouth.speaks = function(what_is_said){
console.log('loudmouth: ' + what_is_said);
this.mouth.emit('elevator gossip', what_is_said);
};
james.enter_elevator();
mary.enter_elevator();
loudmouth.speaks('boss is having an affair');
james.leave_elevator();
loudmouth.speaks('just kidding');
console.log('james did not hear the last line because he was not listening anymore =)');
so in this 'story' the actors choose to listen or when to not listen for events from a third party. I hope this helps.
At work, we have a huge framework and use events to send data from one part of it to another. I recently started a personal project and I often think to use events to control the interactions of my objects.
For example, I have a Mixer class that play sound effects and I initially thought I should receive events to play a sound effect. Then I decided to only make my class static and call
Mixer.playSfx(SoundEffect)
in my classes. I have a ton of examples like this one where I initially think of an implementation with events and then change my mind, saying to myself it is too complex for nothing.
So when should I use events in a project? In which occasions events have a serious advantage over others techniques?
You generally use events to notify subscribers about some action or state change that occurred on the object. By using an event, you let different subscribers react differently, and by decoupling the subscriber (and its logic) from the event generator, the object becomes reusable.
In your Mixer example, I'd have events signal the start and end of playing of the sound effect. If I were to use this in a desktop application, I could use those events to enable/disable controls in the UI.
The difference between Calling a subroutine and raising events has to do with: Specification, Election, Cardinality and ultimately, which side, the initiator or the receiver has Control.
With Calls, the initiator elects to call the receiving routine, and the initiator specifies the receiver. And this leads to many-to-one cardinality, as many callers may elect to call the same subroutine.
With Events on the other hand, the initiator raises an event that will be received by those routines that have elected to receive that event. The receiver specifies what events it will receive from what initiators. This then leads to one-to-many cardinality as one event source can have many receivers.
So the decision as to Calls or Events, mostly has to do with whether the initiator determines the receiver is or the receiver determines the initiator.
Its a tradeoff between simplicity and re-usability. Lets take an metaphor of "Sending the email" process:
If you know the recipients and they are finite in number that you can always determine, its as simple as putting them in "To" list and hitting the send button. Its simple as thats what we use most of the time. This is calling the function directly.
However, in case of mailing list, you don't know in advance that how many users are going to subscribe to your email. In that case, you create a mailing list program where the users can subscribe to and the email goes automatically to all the subscribed users. This is event modeling.
Now, even though, in both above option, emails are sent to users, you are a better judge of when to send email directly and when to use the mailing list program. Apply the same judgement, hope that you would get your answer :)
Cheers,
Ajit.
I have been working with a huge code base at my previous work place and have seen, that using events can increase the complexity quite a lot and often unnecessarily.
I had often to reverse engineer existing code in order to fix it or to extend it.
In both cases, it is a lot easier to understand what is going on, when you can simply read a list of function calls instead of just seeing the raise of an event.
The event forces you to look for usages in order to fully understand what is happening. Not a problem with modern IDEs, but if you then encounter many functions, which also raise events, it quickly becomes complex. I had encountered cases, where it mattered in what order functions did subscribe to an event, even though most languages don't even gurantee a calling order...
There are cases when it is a really good idea to use events. But before you start eventing, consider the alternative. It is probably easier to read and mantain.
A Classic example for the use of events is a UI framework, which provides elements like buttons etc.
You want the function "ButtonPressed()" of the framework to call some of your functions, so that you can react to the user action.
The alternative to an event that you can subscribe to, would for example be a public bool "buttonPressed", which the UI framework exposes
and which you can regurlary check for beeing true or false. This is of course very ineffecient, when there are hundreds of UI elements.