Pusher Events
Events are the primary method of packaging messages in the Pusher system. they form the basis of all communication.
They are essentially ‘named messages’ which means you can set up ‘handlers’ in your client code to deal with the various types. As such they are used for ‘client-side’ routing, and should not be used as filters (channels can do this much more efficiently on the server side).
Events can be seen as a notification of something happening on your system, and they are often named in the past tense. For example: message-created, todo-finished.
Binding to Events
Most binding and triggering behaviour is attached to channels the client is subscribed to, though it is also possible to bind to all events on the pusher connection regardless of the channel.
channel.bind
Events can be bound to directly on a channel which means you will only received an event if it is sent on that specific channel.
channel.bind(eventName, callback);
- eventName (String)
- The name of the event to bind to.
- callback (Function)
- A function to be called whenever the event is triggered.
Example
The following might be an example of a stock tracking app where several channels are opened for different companies:
var pusher = new Pusher('API_KEY');
var channel = pusher.subscribe('APPL');
channel.bind('new-price',
function(data) {
// add new price into the APPL widget
}
);
pusher.bind
You can bind to events regardless of the channel the event is broadcast to. The following is an example of an app that binds to new comments from any channel:
pusher.bind(eventName, callback);
- eventName (String)
- The name of the event to bind to.
- callback (Function)
- A function to be called whenever the event is triggered.
Example
var pusher = new Pusher('API_KEY');
var eventName = 'new-comment';
var callback = function(data) {
// add comment into page
};
pusher.bind(eventName, callback);
Binding to all events from the connection
It is possible to bind to all events at either the global or channel level by using the method bind_all. This is used for debugging, but may have other utilities.
Unbinding from Events
channel.unbind
It’s possible to removing a binding to an event on a channel.
channel.unbind(eventName, callback);
- eventName (String)
- The name of the event that the binding is to be removed from.
- callback (Function)
- A function event handler used when binding to the event.
Example
var pusher = new Pusher('API_KEY');
var channel = pusher.subscribe('APPL');
var callback = function(data) {};
channel.bind('new-price', callback);
channel.unbind('new-price', callback)
Pusher channel events
Some events are triggered by Pusher and to clearly indicate this are prefixed with pusher:.
pusher:subscription_succeeded
Note: this feature was introduced in version 1.10 of the Pusher JavaScript library.
Once you’ve subscribed to a channel you can bind to the pusher:subscription_succeeded event so that you know when the subscription has been registered within Pusher.
channel.bind('pusher:subscription_succeeded', function() {
});
This is particularly useful for private and presence channels if you are using client events because you can only trigger an event once a successful subscription has occurred.
If the channel is a Presence Channel a members event argument is also passed to the pusher:subscription_succeeded event handler. The presence channel also introduces a number of other events that can be bound to. For information please see the presence events docs.
pusher:subscription_error
Note: the pusher:subscription_error event was introduced without the pusher: prefix but this is required in version 1.10 of the Pusher JavaScript library and up.
Sometimes things go wrong so we’ve exposed a pusher:subscription_error event that is triggered when an authentication request for a private or presence channels fails. This event is bound to on the channel that is to be authenticated.
channel.bind('pusher:subscription_error', function(status) {
});
- status (Number)
- The HTTP Status code of the error response from the authentication call.
Example
var pusher = new Pusher('APP_KEY');
var channel = pusher.subscribe('private-channel');
channel.bind('pusher:subscription_error', function(status) {
if(status == 408 || status == 503){
// retry?
}
});
Additional presence events
Presence comes with a number of presence specific events. For more information please see the presence events docs.
Triggering Client Events
Not all traffic needs to go via your conventional web server when using Pusher. Some actions may not need validation or persistence and can go directly via the socket to all the other clients connected to the channel.
It is important that you apply additional care when when using client events, since these originate from other users, and could be subject to tampering by a malicious user of your site.
Client events have a number of enforced restrictions to ensure that the user subscribing to the channel is an authenticated user and so that client events can be clearly identified:
- Client events must be enabled for the application. You can do this in the Settings tab for your app within the Pusher dashboard
- The user must be subscribed to the channel that the event is being triggered on
- Client events can only be triggered on private and presence channels because they require authentication
- Client events must be prefixed by
client-. Events with any other prefix will be rejected by the Pusher server, as will events sent to channels to which the client is not subscribed. - You can only trigger a client event once a subscription has been successfully registered with Pusher. You can ensure this is the case using the
pusher:subscription_succeededevent. - Client events are not delivered to the originator of the event. For more information see Message Routing.
- Publish no more than 10 messages per second per client (connection). Any events triggered above this rate limit will be rejected by our API. See Rate limit your events.
var triggered = channel.trigger(eventName, data);
- eventName (String)
- The name of the event to be triggered. A client event must have a name prefixed with client- or it will be rejected by the server.
- data (Object)
- The object to be converted to JSON and distributed with the event.
- Returns (Boolean)
trueif the event was successfully triggered, otherwisefalse
Example
var pusher = new Pusher('YOUR_APP_KEY');
var channel = pusher.subscribe('private-channel');
channel.bind('pusher:subscription_succeeded', function() {
var triggered = channel.trigger('client-someeventname', { your: data });
});
Message routing
When you trigger a client event, the event will not be fired in the browser which calls trigger. This is similar to the case described in the page on excluding event recipients.
Best practice when sending client events
As well as the obvious security implications of sending messages from clients, and in particular web browsers, it’s also important to consider what events are sent and when. If the destination client is also a web browser there is only so much data that web browser can handle so there only the required information should be sent at the right time. With this in mind we’ve come up with a few best practice guidelines to follow when trigger client events.
Rate limit your events
Publish no more than 10 messages per second per client (connection). Any events triggered above this rate limit will be rejected by our API.
This is not a system issue, it is a client issue. 100 clients in a channel sending messages at this rate would each also have to be processing 1,000 messages per second! Whilst some modern browsers might be able to handle this it’s most probably not a good idea.
When to trigger events
The obvious things that result in events being triggered from a client application with a user interface are user actions such as mouse movement or key presses. In this scenario we still need to consider limiting how much information we send. Quite frequently a UI event should not lead directly to a client event being published into Pusher.
For example, if you have bound the the mousemove event and a user is wildly waving their pointer around the screen it’s not a good idea to translate each mouse move event into a client event. Instead you should define an interval at which the mouse position should be sent and if the mouse position has moved when the next interval fires send a single client event. The time interval may need to be tuned to suit your requirements.
Example
Information to appear here
var outputEl = document.getElementById('client_event_example_log');
var state = {
currentX: 0,
currentY: 0,
lastX: undefined,
lastY: undefined
};
var pusher = new Pusher("YOUR_APP_KEY");
var channel = pusher.subscribe("private-mousemoves");
// this method should be bound as a 'mousemove' event listener
document.body.addEventListener('mousemove', onMouseMove, false);
function onMouseMove(ev){
ev = ev || window.event;
state.currentX = ev.pageX || ev.clientX;
state.currentY = ev.pageY || ev.clientY;
}
setInterval(function(){
if(state.currentX !== state.lastX || state.currentY !== state.lastY){
state.lastX = state.currentX;
state.lastY = state.currentY;
var text = document.createTextNode(
'Triggering event due to state change: x: ' + state.currentX + ', y: ' + state.currentY
);
outputEl.replaceChild( text, outputEl.firstChild );
channel.trigger("client-mouse-moved", {x:state.currentX, y: state.currentY});
}
}, 300); // send every 300 milliseconds if position has changed
