I am using ionic with vue js mobile app. I want to trigger event from client side when location on mobile user is changed.
methods: {
getLocation: function () {
const geolocation = new GeolocationService.Geolocation();
let watch = geolocation.watchPosition();
watch.subscribe((data) => {
console.log('data',data)
//Trigger pusher event here
});
},
},
And then I want to listen that event on my web app with help of jquery.
But I don't know how I can trigger pusher event from client side
I am using this pusher package
https://www.npmjs.com/package/vue-pusher
The Pusher documentation about triggering client events has every information for your case.
Starting with:
Not all traffic needs to go via your conventional web server when using Channels. Some actions may not need validation or persistence and can go directly via the socket to all the other clients connected to the channel.
Some other important things to highlight:
Client events must be enabled for the application inside 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. So understanding Pusher authentication is a must.
Publish no more than 10 messages per second per client (connection). So user location changing every second shouldn't be a problem.
Using a wrapper like vue-pusher is totally optional, you can always instantiate a new Pusher and use the client directly. But if you really like the wrapper, your code could be something like that:
export default {
data() {
return {
channel: null
};
},
created() {
this.channel = this.$pusher.subscribe('private-positions');
},
methods: {
getLocation() {
const geolocation = new GeolocationService.Geolocation();
const watchPosition = geolocation.watchPosition();
watchPosition.subscribe((data) => {
this.channel.trigger("client-positionChanged", {
data
});
});
}
}
}
Of course the Pusher authentication part should be considered too.
Related
I'm making a clone of discord and right now I'm trying to implement the online/offline functionality of the server users. I'm trying to implement it like this:
When a user joins a server, I emit a userCameOnline event with the username of the user:
state.socket.emit('userCameOnline', state.username)
Then on the back-end, I listen for that event and once I receive it, I set the socket's username to the emitted username, then push that username to an array of online users and finally, I emit back an event called onlineUsers:
socket.on('userCameOnline', (username) => {
socket.username = username
onlineUsers.push(socket.username)
console.log(onlineUsers)
socket.emit('onlineUsers', onlineUsers)
})
And this is the onlineUsers listener on the front-end that sets onlineUsers property to the server:
state.socket.on('onlineUsers', (onlineUsers) => {
console.log(onlineUsers)
server.onlineUsers = onlineUsers
})
Now here's the problem. The onlineUsers listener works when I load the page the first time, however, when I open a second browser and join the chat with another account, the client emits these events again with the new user:
state.socket.emit('userCameOnline', state.username)
I know this is working fine as I console.log(onlineUsers) on the back-end and see that the array indeed has 2 users once the second client has joined. This means that this works:
socket.on('userCameOnline', (username) => {
socket.username = username
onlineUsers.push(socket.username)
console.log(onlineUsers)
socket.emit('onlineUsers', onlineUsers)
})
Unfortunately, the onlineUsers listener on the first client doesn't trigger which means that the onlineUsers property of the server doesn't get updated with the newly joined user. I've been banging my head for some time now and I can't figure out why is this happening. I've been following the trail and console.logging everything but I still can't figure it out.
This is why I am wondering why does this:
state.socket.on('onlineUsers', (onlineUsers) => {
console.log(onlineUsers)
server.onlineUsers = onlineUsers
})
Triggers once I load the page and then doesn't trigger anymore even though I'm emitting the event from the back-end every time a new user joins the server?
So, if i understand your problem then instead of emitting in the Back-end:
socket.emit('onlineUsers', onlineUsers)
You should emit :
io.emit('onlineUsers', onlineUsers)
Because by emitting with socket.emit() you will end up emitting only to the same client that emitted to the server in the first place.
As with io.emit() you will emit to all of your clients.
Assuming that you are using something like :
const io = require('socket.io')(server, {(your_args)})
If you want to check for further information on how to use the emit function
check out this page https://socket.io/docs/emit-cheatsheet/ from their website.
Finally i would highly recommend you to check out their API documentation and other blogs about it
I have implemented firebase cloud messaging for my react-native app and now I am able to send and receive Notifications.
But now I want to get the Notifications Data like messages, right after clicking on it.
Why I need this ?
Because I have A simple chat app, and suppose I have three rooms, room1, room2, room3.
Now my App is closed and I receive Notification from room1, then I click on that, At this time I expected it open my app and navigate to the room1 chatbox, and the other rooms notifications too.
Any help?
note: I am using react-native-firebase v6
Cloud Messaging is only used to send messages from a server on the phone.
Before, on firebase 5, we had a package called "notifications" which allowed us to manage the interception of data when you clicked on it.
Since Firebase 6, this package doesn't exist anymore (well, in a way it will become paying and this service is called Notifee but it is still in test).
You have to use external packages such as react-native-push-notifications which allows you to intercept push notifications data.
async componentDidMount() {
this.createNotificationListeners();
}
async createNotificationListeners() {
this.notificationListener = firebase.notifications().onNotification((notification) => {
console.log(':::::::::::::::::::::::::::: APPLICATION OPEN MODE :::::::::::::::::::::::::::');
console.log(notification, 'APPLICATION OPEN');
// Manage Notifiacation
// firebase.notifications().removeDeliveredNotification(notification._notificationId);
});
const channel = new firebase.notifications.Android.Channel('fcm_FirebaseNotifiction_default_channel', 'JobApp', firebase.notifications.Android.Importance.High)
.setDescription('DEMO NOTIFICATION DESCRIPTION');
firebase.notifications().android.createChannel(channel);
this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen) => {
console.log(':::::::::::::::::::::::::::: APPLICATION WORKING IN BACKGROUND MODE :::::::::::::::::::::::::::');
console.log(notificationOpen.notification.data);
const { notificationType } = notificationOpen.notification.data;
console.log(notificationType)
firebase.notifications().removeDeliveredNotification(notificationOpen.notification._notificationId);
});
const notificationOpen = await firebase.notifications().getInitialNotification();
if (notificationOpen) {
console.log(':::::::::::::::::::::::::::: APPLICATION CLOSED :::::::::::::::::::::::::::');
console.log(notificationOpen);
}
this.messageListener = firebase.messaging().onMessage((message) => {
console.log(JSON.stringify(message));
});
}
i'm trying to create custom API listener for 3-rd developers on my site. It should look like this:
// Function will be fired when any user joins to room
API.on('user-join', function(data){
console.log(data); // Data is object with user id and name
});
I have Socket.io listener too:
// This handler is fired every time when anyone joins
socket.on('user-join', function(data){
// Probably here i should call a callback to API.on('user-join') with that data object
});
How can i send callback in Socket.io handler to my custom created API? Please let me know how to do this. Thanks.
Not sure what you are trying to do, but if I understand correctly, you want to map the "on" function of the socket.io API to your API.
The best way to do this would be to implement a function like this:
API.on = (eventName, callback) => {
socket.on(eventName, callback);
}
Where eventName is a string and callback a function.
This way, you can add an event listener to your API, the same way you would with Socket.io
Eg:
API.on('testEvent', (obj) => {console.log(obj});
you are mixing things up.
your socket API will need a server-side listener independent from your socket API, that, as far as i understood, manages the IO with the connected clients, am i right?
In this case, you don't have to bind anything. You need a controller for your API sockets and your client's controller have to trigger events to those users.
a client connects to your site
a notification is received by the server
the server notifies to the API users
here's some pseudocode, please don't use it, it just illustrates a concept :D
const thrdUsers = [.....] // socket connections
const onThirdUserConnects = socket => thrdUsers.push(socket);
API.on('connect', onThirdUsersConnects);
// Then you need a broadcast function to send events to all your clients
const broadcastToAPI = (msg, val) => thrdUsers.forEach(s => s.send(msg, val));
// Your users will trigger events to your socket.io service
socket.on('whatever-event', (data) => {
//...Do stuff
// notify the API clients
broadcastToAPI('whatever-event', data);
});
I am trying to create an app that uses websockets, but am running into the dreaded "multiple connection" issue where everytime the page is reloaded rather than closing and reopening a new websocket, another connection is simply added to the list. My question is if anyone knows the best/proper way to close a Socket.io websocket from Angular 2/4+.
Here's what I have as far as code:
service.ts
getUserSocket(userID: string): Observable<any> {
return new Observable(_Observer => {
// Setup the socket namespace subscription
this.UserSocket = io(NTC_API_URL + `/user/${userID}`, { secure: true });
this.UserSocket.on('message', _Message => {
console.log(_Message);
})
})
}
closeUserSocket() {
this.UserSocket.disconnect();
this.UserSocket.close();
}
component.ts
ngOninit() {
// Setup the User Socket
this.UserSocket = this._UsersService.getUserSocket(this.currentUser.userID)
.subscribe(_UserSocketMessage => {
console.log(_UserSocketMessage);
})
}
ngOnDestroy() {
this.UserSocket.unsubscribe();
this._UsersService.closeUserSocket();
}
This doesn't seem to be working as I can still watch the connections pile up just by logging in an out of the application which I have confirmed calls the component to be destroyed.
Another option I tried was using the once listener instead of the on listener, which worked, but I am unsure about the side effects and have read several places that it's not necessarily a fix for not closing the connection, which I can understand.
After quite a bit of tinkering and research it occurred to me that web sockets are made to be resilient. In other words, since they were engineered to reconnect if possible, focusing on disconnect and close was the wrong approach. It was far easier to enforce policies with regard to the Creation of web socket connections.
For starters, I had to refactor a few things on the server side to make sure particular namespaces were only initialized once. This wasn't achieved so much by altering initialization code as it was by making sure that web socket initialization only occurred in places that either only happened on startup, or during processes that are only highly likely to happen once such as a particular user being created.
On the angular side it was also pretty straightforward in that all I had to do was assign the socket to a property within the service, then check if it existed before making the socket connection. Hence only creating the connection if no connection existed previously.
service.ts
// Setup the socket namespace subscription
if (!this.UserSocket) {
// Initialize user permissions socket
this.UserSocket = io(NTC_API_URL + `/user/${this.LocalUser.userID}`, { secure: true });
}
I'm getting a Pusher subscribe/un-subscribe problem with presence groups on a fairly simple chat application. There should be two subscribed channels at a given time. Users switch between channels when navigating between backbone routes, so there are no hard page reloads.
Pusher appears to function most of the time, but I get intermittent errors for channel subscriptions.
I wrote two join channel methods that unsubscribe if one has been joined by a previous route. I'm worried that there is something async happening within Pusher that is breaking things.
My pusher related code for a single channel:
window.pusher = new Pusher('<%= Pusher.key %>', {
authEndpoint: 'api/pusher/auth'
});
Route:
this.groupFeed = this._pusherSubscribeGroup(group_id);
this.groupFeed.bind('new_conversation', function(data) {
var newConv = new App.Models.Conversation(data);
this.group.conversations().add(newConv);
}.bind(this));
Unsubscribe helper:
_pusherSubscribeGroup: function (group_id) {
if (this._groupChannelName) {
window.pusher.unsubscribe(this._groupChannelName);
}
this._groupChannelName = 'presence-group-' + group_id;
return window.pusher.subscribe(this._groupChannelName);
}
Console error:
Pusher : Error : {"type":"WebSocketError","error":{"type":"PusherError","data":{"code":null,"message":"Existing subscription to channel presence-group-1"}}}
Pusher : Error : {"type":"WebSocketError","error":{"type":"PusherError","data":{"code":null,"message":"Existing subscription to channel presence-group-1"}}}
The message is telling you that - as far as the Pusher service is concerned - this particular client identified by a socket_id is already subscribed to the presence-group-1 channel. From the point of view of the client this error normally isn't something you actually need to worry about.
However, if the user is quickly subscribing/unsubscribing by navigating routes it would be worth getting some more information to be completely sure. From the supplied code and description, it's not possible to determine if the problem is within the Pusher service or the client application.
Providing the output of the Pusher JavaScript library logging will provide more detail that could help determine the cause.