getSubscription upon activation of sw - javascript

I'm not sure where I'm making a mistake.
I want to register a service worker and the moment it's "activated"
make an XHR request to my server in order to store the subscription data.
self.addEventListener('activate', function(event) {
console.log('Activated', event);
event.waitUntil(
self.registration.pushManager.getSubscription().then(function (subscription) {
console.log(subscription);//this is always null
})
)
})
So far I wasn't able to get the subscription inside the SW, I can from any other javascript on the site. What am I not udnerstanding?
Edit:
this is how I register to pushmanager
function reg(){
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register(SW).then(function(reg) {
reg.pushManager.subscribe({
userVisibleOnly: true
}).then(function(subscription) {
send_subscription(subscription);
});
}).catch(function(error) {
console.log(':^(', error);
});
}
}
function send_subscription(subscription){ [...] }

You are attempting to get the subscription to a PushManager:
The PushManager.getSubscription() method of the PushManager interface retrieves an existing push subscription.
If this is intended, you first have to subscribe a PushManager using PushManager.subscribe().

Related

How to mock/simulate in the jest test PubNub event which added in pubnub.addListener?

I have a package that uses PubNub, I', try to cover all package files with jest tests, but I have a problem: I can't find the way to cover events inside the listener
// add listener
const listener = {
// Need to cover these cases (status and message)
status: (statusEvent) => {
if (statusEvent.category === "PNConnectedCategory") {
console.log("Connected");
}
},
message: (messageEvent) => {
// Process message
}
};
this.pubnub.addListener(listener);
this.pubnub.subscribe({
channels: [this.channel]
});
I attached a screen with the part which I need to cover test
[![uncovered file part][1]][1]
How to mock/simulate in the jest test PubNub event which added in pubnub.addListener?
describe("publishPubNub test suites", () => {
const sideEffect = function (options) {
pubnubService.publishPubNub(options);
return true;
}
it("successfull", () => {
//TODO: mock event here
const isCompleted = sideEffect(publishPubNubOptions)
expect(isCompleted).toBeTruthy();
});
})
Thanks for any helps or advice.
[1]: https://i.stack.imgur.com/tF3c2.png
The listener status handler will be invoked whenever a connection is established (or some other connection event happens). The message handler will be invoked whenever your application receives a message that it has previously subscribed to.
You could either:
Test your application against a real PubNub instance, though that would require an Internet connection.
Create a mocked library. PubNub does not offer an official mocked library so you would need to roll your own. Something like the following based on your image:
'use strict';
class PubNub {
constructor(pubKey, subKey, uniqueId) {
this.listener = {}
}
addListener(listener) {
this.listener = listener;
}
subscribe(channelsObj) {
this.listener.status({"category": "PNConnectedCategory"})
}
publishPubNub(options) {
this.listener.message({"message": {"request": {"decision": "approved"}}})
}
}
module.exports = PubNub;

Apply error handling in react google analytics

I am using react-ga (https://www.npmjs.com/package/react-ga) module in my React application, so that i can send events, to google analytics.
I have read the documentation of react-ga and i cant find a way to have a response after i send data to google analytics.
The way i m sending data is like so:
import * ReactGA from 'react-ga'
function sendEvent(category: string, action: string, label: string) {
ReactGA.event({
category,
action,
label,
});
}
function sendPageView(title: string, url: string) {
ReactGA.set({ page: title });
ReactGA.send()
ReactGA.pageview(url);
}
These are just calls to google-analytics, without any feedback, What i m looking for is a function that get a callback OR an async function, that executes the above.
POST request to google-analytics:.
Actually, there is an automatic POST request, each time i m sending an event, which fetches 1 on response.(i dont control the POST request)
The request is like so: Request URL: https://www.google-analytics.com/j/collect?v=1&_v=....
What i try to accomplish, is to catch Errors and send them to Sentry server:.
get errors, in case google analytics server is not responding
get error, in case there is a timeout, on the response of google-analytics.com.
Possibly this module is restricted on functionality, has anyone else used something similar and managed to get any kind of Errors ?
thanks.
I solved the case, based on the official google-analytics documentation: https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#hitCallback
I attach the solutions, for reference:
Send an event and call the callback function when completed:
ReactGA.ga('send', 'event', 'Page view' {
hitCallback: (res: any) => {
console.log('*** page view event success.');
return true;
},
});
Send an event and time it to 1sec.
If the callback is not executed by then, i raise a timeout error, otherwise i execute the success code:
let alreadyCalled: boolean = false;
function myCode(timeout: boolean, hasResponded: boolean) {
if (alreadyCalled) return;
alreadyCalled = true;
if (timeout === true && hasResponded === false) {
// TODO, THROW AN ERROR AND SEND TO SENTRY
console.log('Time out error, sending message to Sentry..');
} else if (timeout === false && hasResponded === true) {
// TODO, send event success
console.log('send event to google-analytics, success');
}
}
ReactGA.ga('send', 'event', 'pageview', { hitCallback: () => myCode(false, true) });
setTimeout(() => myCode(true, false), 10);
I hope it helps anyone that needs something similar.

How to Observe a Custom Event using RXJS in Angular 2?

I have a third party library that I am intending to integrate with RxJS. This is a messaging library called Tiger Text. According to them I can listen to an event called messages and when the stream has a message I can use it to further utilize it. The code snippet for the same is as follows:-
var client = new TigerConnect.Client({ defaultOrganizationId: 'some-org-id' })
client.signIn('user#mail.com', 's3cr3t', { udid: 'unique-device-id' }).then(function (session) {
onSignedIn(session)
})
function onSignedIn(session) {
console.log('Signed in as', session.user.displayName)
client.messages.sendToUser(
'someone#mail.com',
'hello!'
).then(function (message) {
console.log('sent', message.body, 'to', message.recipient.displayName)
})
client.events.connect()
client.on('message', function (message) {
console.log(
'message event',
message.sender.displayName,
'to',
message.recipient.displayName,
':',
message.body
)
})
}
Now please have a look at the place where you have the below mentioned piece of code.
client.on('message', function (message) {
console.log(
'message event',
message.sender.displayName,
'to',
message.recipient.displayName,
':',
message.body
)
})
I wanted to know how to use RxJS so as to create an observable out of this piece of code so as to subscribe to the stream and whenever we have a change I take the new data and process it as I wish.
Please Advice.
For this use-cases you typically don't need to write a custom Observable and you can use just Observable.create(). Then it depends on whether you want to write a cold or a hot observable.
For cold Observables you create the producer of values when subscribing and close it when unsubscribing:
Observable.create(obs => {
var client = new TigerConnect.Client({ defaultOrganizationId: 'some-org-id' });
client.signIn('user#mail.com', 's3cr3t', { udid: 'unique-device-id' }).then(function (session) {
onSignedIn(session);
});
client.on('message', function (message) {
obs.next(...);
});
return () => {
client.close(); // or whatever...
};
});
Or if you want to write a hot Observable the producer will exist independently on any subscriptions and just add/remove the listener:
var client = new TigerConnect.Client({ defaultOrganizationId: 'some-org-id' });
client.signIn('user#mail.com', 's3cr3t', { udid: 'unique-device-id' }).then(function (session) {
onSignedIn(session);
});
Observable.create(obs => {
let listener = client.on('message', function (message) {
obs.next(...);
});
() => {
// remove the event listener somehow
listener.remove();
};
});
Sometimes you can see this solved by using a Subject but this is usually more complicated than using Observable.create() because then you need to handle the creation and tear down logic yourself and also Subjects have internal state.
Here's a very similar question as yours:
Subscribe to a stream with RxJS and twitter-stream-api module
Articles on the topics related to your question by the lead developer of RxJS:
https://medium.com/#benlesh/hot-vs-cold-observables-f8094ed53339
https://medium.com/#benlesh/on-the-subject-of-subjects-in-rxjs-2b08b7198b93
https://medium.com/#benlesh/rxjs-dont-unsubscribe-6753ed4fda87
https://medium.com/#benlesh/learning-observable-by-building-observable-d5da57405d87
You can use fromEventPattern to create an observable from a custom event:
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromEventPattern';
const messages = Observable.fromEventPattern(
handler => client.on('message', handler),
handler => client.off('message', handler)
);
messages.subscribe(message => console.log(message));
You pass to fromEventPattern functions that add and remove the event handler using the custom API's add and remove mechanism. You've not included it in your question, but I've assumed the API you're using implements an off method.

Handle Push notification in Nativescript

I am working on application in Nativescript which implements push notification. Lets say server sends push notification and based on action mentioned in payload of notification i will have to redirect in application. This redirection should be performed if user taps on notification from drawer and application is in background. Other case when application should not redirect if its in foreground. I have managed a flag for that as follow
app.js
application.on(application.launchEvent, function (args) {
appSettings.setBoolean('AppForground', true);
});
application.on(application.suspendEvent, function (args) {
appSettings.setBoolean('AppForground', false);
});
application.on(application.resumeEvent, function (args) {
appSettings.setBoolean('AppForground', true);
});
application.on(application.exitEvent, function (args) {
appSettings.setBoolean('AppForground', false);
});
application.on(application.lowMemoryEvent, function (args) {
appSettings.setBoolean('AppForground', false);
});
application.on(application.uncaughtErrorEvent, function (args) {
appSettings.setBoolean('AppForground', false);
});
And on Push notification listener
var settings = {
// Android settings
senderID: '1234567890', // Android: Required setting with the sender/project number
notificationCallbackAndroid: function(data, pushNotificationObject) { // Android: Callback to invoke when a new push is received.
var payload = JSON.parse(JSON.parse(pushNotificationObject).data);
if (appSettings.getBoolean('AppForground') == false){
switch (payload.action) {
case "APPOINTMENT_DETAIL":
frame.topmost().navigate({
moduleName: views.appointmentDetails,
context: {
id: payload.id
}
});
break;
case "MESSAGE":
frame.topmost().navigate({
moduleName: views.appointmentDetails,
context: {
id: payload.id,
from: "messages"
}
});
break;
case "REFERENCES":
frame.topmost().navigate({
moduleName: views.clientDetails,
context: {
id: payload.id,
name: ""
}
});
break;
default:
}
}
},
// iOS settings
badge: true, // Enable setting badge through Push Notification
sound: true, // Enable playing a sound
alert: true, // Enable creating a alert
// Callback to invoke, when a push is received on iOS
notificationCallbackIOS: function(message) {
alert(JSON.stringify(message));
}
};
pushPlugin.register(settings,
// Success callback
function(token) {
// if we're on android device we have the onMessageReceived function to subscribe
// for push notifications
if(pushPlugin.onMessageReceived) {
pushPlugin.onMessageReceived(settings.notificationCallbackAndroid);
}
},
// Error Callback
function(error) {
alert(error);
}
);
Now the problem, is that if application is in killed state and notification arrives. Then it sets flag to true as application is launched which it should not. So due to that redirection is not performed and in other cases when application is in foreground state then also its navigating through pages (which should not be) on receiving notification.
I doubt about flag management is causing the problem but not sure. Would you please guide me if anything is wrong with what i did ?
UPDATE
I am using push-plugin.
Thanks.
I use this for notifications
https://github.com/EddyVerbruggen/nativescript-plugin-firebase
This plugin use FCM, it adds to datas received from notifications foreground parameter so from payload you can determine if app was background(foreground==false, app is not active or was started after notification arrived) or foreground(foreground==true, app is open and active), but you need to some changes to code as they are different plugins
You can use pusher-nativescript npm module.
import { Pusher } from 'pusher-nativescript';
/*Observation using the above.
- Project gets build successfully.
- on run -> ERROR TypeError: pusher_nativescript__WEBPACK_IMPORTED_MODULE_6__.Pusher is not a constructor
- Use: import * as Pusher from 'pusher-nativescript';
- Make sure to install nativescript-websocket with this package.
*/
var pusher = new Pusher('Your_app_key', { cluster: 'your_cluster_name' });
var channel = pusher.subscribe('my-channel');
channel.bind('my-event', function(data) {
alert(JSON.stringify(data));
});

How to reconnect after you called .disconnect()

Question: How do you reconnect a client to the server after you have issued a manual .disconnect()?
In my current project, I need to disconnect a client from the server when the user log out from the session. I did a socket.disconnect() to do the disconnection successfully. Server removed the user from the session.
After awhile, the user decided to login again, but socket.io refuses to connect.
I am clear that Socket.IO has implemented reconnection algorithm but clearly this is a different case.
Below is the piece of code where I do the connection. On second trigger of this block of code, object socket was created, but no connect was fired from this object.
//Start the socket
var socket = io.connect(SOCKET_IO_URL);
socket.on('connect', function() {
me.fireEvent('connect');
socket.emit('register', {
hashed_identifier: hashed_identifier,
account_id: account_id
});
});
socket.on('ready', function() {
me.ready = true;
me.log('Handshake done. Listening for new data');
});
socket.on('data', function(data) {
me.fireEvent('data', data);
//Tells server we received it
socket.emit('data', {ack: 1});
});
socket.on('disconnect', function() {
me.fireEvent('disconnect');
});
UPDATE: As requested by #Tony
In fact the whole thing is wrapped under Sencha Touch 2.0, but I believe there is nothing to do with ST2.0
This is my Data Class. Usage of this class is when the user logged in, this class will get initialized. And upon the user logout, the system will call the disconnect() method in this class.
When the user login again, this class is initialized again, but funny is the socket somehow retained all the previous events and sessions it has previously.
/**
* Serve as interface to wait for data communication in between server and client
*/
Ext.define('go.module.connect.Data', {
mixins: {
observable: 'Ext.mixin.Observable'
},
config: {
account: null
},
ready: false,
socket: null,
constructor: function(cfg) {
var me = this,
hashed_identifier = Sha1.hash(go.__identifier);
me.initConfig(cfg);
var account_id = me.getAccount().get('id');
//Start the socket
var socket = io.connect(SOCKET_IO_URL);
socket.on('connect', function() {
console.log('connect');
me.fireEvent('connect');
socket.emit('register', {
hashed_identifier:hashed_identifier,
account_id: account_id
});
});
socket.on('ready', function() {
me.ready = true;
me.log('Handshake done. Listening for new data');
});
socket.on('data', function(data) {
me.fireEvent('data', data);
//Tells server we received it
socket.emit('data', {ack: 1});
});
socket.on('disconnect', function() {
me.fireEvent('disconnect');
});
console.log(socket);
if (!socket.socket.connected){
socket.socket.reconnect();
}
me.socket = socket;
me.callParent([cfg]);
},
disconnect: function() {
this.socket.disconnect();
this.socket.removeAllListeners();
this.socket.socket.removeAllListeners();
},
log: function(msg) {
console.log('## Connect: '+msg);
}
});
And below is my console.log results:
And below is my node.js debug window
I believe the root cause of this funny scenario is that the previously attached connect event listener is not removed thoroughly. How should I remove it? Should I use once? or I should specify the listener function as well. I thought removeAllListeners() is sufficient for this task.
The standard approach in latest socket.io is:
socket.on('disconnect', function() {
socket.socket.reconnect();
})
This is what I've been using in my app and works great. It also ensures that the socket keeps trying to reconnect if the server goes way, and eventually reconnects when the server is back online.
In your case, you need to ensure two things:
You create your socket only once. Don't call socket = io.connect(...) more than once.
You setup your event handling only once - otherwise they will be fired multiple times!
So when you want to reconnect the client, call socket.socket.reconnect(). You can also test this from the browser console in FireFox and Chrome.
You can reconnect by following client side config.
// for socket.io version 1.0
io.connect(SERVER_IP,{'forceNew':true };
I'm doing this way with socket.io 1.4.5 and it seems to work, for now:
var app = {
socket: null,
connect: function() {
// typical storing of reference to 'app' in this case
var self = this;
// reset the socket
// if it's not the first connect() call this will be triggered
// I hope this is enough to reset a socket
if( self.socket ) {
self.socket.disconnect();
delete self.socket;
self.socket = null;
}
// standard connectiong procedure
self.socket = io.connect( 'http://127.0.0.1:3000', { // adapt to your server
reconnection: true, // default setting at present
reconnectionDelay: 1000, // default setting at present
reconnectionDelayMax : 5000, // default setting at present
reconnectionAttempts: Infinity // default setting at present
} );
// just some debug output
self.socket.on( 'connect', function () {
console.log( 'connected to server' );
} );
// important, upon detection of disconnection,
// setup a reasonable timeout to reconnect
self.socket.on( 'disconnect', function () {
console.log( 'disconnected from server. trying to reconnect...' );
window.setTimeout( 'app.connect()', 5000 );
} );
}
} // var app
app.connect();
socket.socket.connect();
gets you reconnected.
It seems to me it is how you handle the disconnect...
Worked for me using socket.io - v1.1.0
wrong way...
var sock = io( '/' );
sock.on( 'connect', function(x) { console.log( 'Connected', x ); } );
// now we disconnect at some point:
sock.disconnect();
// now we try to reconnect...
sock.connect()
// or
sock.reconnect();
// - both seem to create the new connection in the debugger, all events are missing though
correct way...
// As above with 3 extra characters, everything functions as expected...
//events fire properly...
sock.io.disconnect();
// consequently i'm also using (for consitency)
sock.io.reconnect();
// sock.connect() still seems to work however.
socket.io v2.0 (current)
For the peoples that was looking as me for the last version please find the doc extract as below:
To manually reconnect:
socket.on('disconnect', () => {
socket.open();
});
socket.io-client v2.2.0
import io from "socket.io-client"
var socket = io(url) // initial connection
const reconnect = () => {
if(!socket.connected) {
socket = io(url) // reconnects to a new socket
}
}

Categories

Resources