Ionic 4 - Platform.resume event calling - angular7

I have an Ionic 4 app in which we have three tabs. Each tab contains data which will be retrieved from api call. The data will change frequently.
When we move between tabs the api will be called and the data will be re-binded. We had a requirement that when the app is minimized and open again the api has to be called and the data has to be re-binded.
I used the platform resume event as below in all the three tabs.
this.platform.ready().then(() => {
this.platform.resume.subscribe((e) => {
// API call of each function (different api for tabs)
});
});
Now, When the app is resumed after minimized, the platform resume event is called by it is calling multiple times as I used resume event in all the three tabs.
Please help to overcome this problem. Thanks in advance.

I'm not sure but what I gather from your question and comments, it would make sense to have a subject that will update on resume and on each tab have the function that request each API listening to that observable?
something like this: (on main app)
this.platform.ready().then(() => {
this.platform.resume.subscribe((e) => {
this.appResumedSubject.next(true);
});
});
and on tab1:
this.appResumedObservable.subscribe(result => {
if(result){
this.apiCall1();
}
});
and on tab2:
this.appResumedObservable.subscribe(result => {
if(result){
this.apiCall2();
}
});
to make it work seamlessly on both tabs it would be needed to have appResumeSubject defined on a service provider.

Related

Twilio Flex Actions Framework (WrapupTask or beforeWrapupTask) event - example not working

Based on the Twilio documentation examples, Actions Framework, I am not having much luck with capturing events for WrapupTask or beforeWrapupTask, it appears the events just never fire and I am not clear on how to go about troubleshooting this?
The code examples I've tired (even identical examples from the documentation) using the latest version of Twilio Flex and the --flexui2 deployment of the Twilio Flex plugin (#twilio-labs/plugin-flex 5.1.2) that don't fire are:
Actions.addListener("beforeWrapupTask", (payload) => {
console.log(`***Task Channel Unique Name: ${payload.task.taskChannelUniqueName}`);
alert("Fired - beforeWrapupTask")
})
or
Actions.addListener("WrapupTask", (payload) => {
console.log(`***Task Channel Unique Name: ${payload.task.taskChannelUniqueName}`);
alert("Fired - WrapupTask")
})
and no luck either with this approach (with many different variations of) - actually the below approach seemed to introduce issues with other events firing like afterAcceptTask for some unknown reason.
flex.Actions.replaceAction("WrapupTask", (payload, original) => {
return new Promise(function(resolve, reject) {
// Send the message:
console.log('***** THIS EVENT FIRED!!!! *****')
}).then(response => {
// Wait until the message is sent to wrap-up the task:
resolve(original(payload));
});
});
Any reason the examples don't work? Has anything changed? I can get beforeCompleteTask working but I really need beforeWrapupTask.
I've exhausted all attempts at finding any information in the documentation or other sources.
Thanks!
So for Voice tasks, it works differently from feedback I received back from a Twilio support ticket. You would take the approach below.
//start listening on reservation created
manager.workerClient.on("reservationCreated", (reservation) => {
//trigger code when wrap-up starts
reservation.on("wrapup", (reservation) => {
alert("End Media Capture - WrapupTask")
});
});

Service-Worker stays in waiting state in Chrome

I'm working on a SPA with Vue. I'd like to update to a new service-worker when the user navigates to a specific page. A save moment to refresh, because the view of the user already changes (a pattern discussed in this video: https://youtu.be/cElAoxhQz6w)
I have an issue that sometimes (infrequently) the service-worker won't activate while calling skipWaiting. The call is made correctly, and even in Chrome I get a response that the current service-worker stops (see animated GIF), however it the same service-worker starts running again, instead of the waiting one.
After a while (1-2 minutes) the service-worker is suddenly activated. Not a situation you want, because it happens just out of the blue when the user might be in the middle of an activity.
Also when I am in this situation I can't activate the service-worker by calling skipWaiting (by doing multiple navigations) again. It's received by the service-worker but nothing happens. It stays in "waiting to activate". When I press skipWaiting in Chrome itself, it works.
I have no clue what goes wrong. Is this an issue with Chrome, workbox or something else?
Most close comes this topic: self.skipWaiting() not working in Service Worker
I use Vue.js, but I don't depend on the pwa plugin for the service-worker. I use the workbox webpack plugin.
I've edited the example code below, the minimal code probably didn't show the problem well
In main.js:
let sw = await navigator.serviceWorker.register("/service-worker.js", {
updateViaCache: "none",
});
let firstSw = false;
navigator.serviceWorker.addEventListener("controllerchange", () => {
// no need to refresh when the first sw controls the page, we solve this with clientsClaim
// this makes sure when multiple-tabs are open all refresh
if (!firstSw) {
window.location.reload();
}
});
sw.onupdatefound = () => {
const installingWorker = sw.installing;
installingWorker.onstatechange = async () => {
console.log("installing worker state-change: " + installingWorker.state);
if (installingWorker.state === "installed") {
if (navigator.serviceWorker.controller) {
firstSw = false;
// set the waiting service-worker in the store
// so we can update it and refresh the page on navigation
await store.dispatch("setWaitingSW", sw.waiting);
} else {
console.log("First sw available");
firstSw = true;
}
}
};
};
In router.js:
// after navigation to specific routes we check for a waiting service-worker.
router.afterEach(async (to) => {
if (to.name == "specificpage") {
let waitingSw = store.getters["getWaitingSW"];
if (waitingSw) {
waitingSw.postMessage("SKIP_WAITING");
// clean the store, because we might have changed our data model
await store.dispatch("cleanLocalForage");
}
}
});
In service-worker.js:
self.addEventListener("message", event => {
if (event.data === "SKIP_WAITING") {
console.log("sw received skip waiting");
self.skipWaiting();
}
});
skipWaiting() isn't instant. If there are active fetches going through the current service worker, it won't break those. If you're seeing skipWaiting() taking a long time, I'd guess you have some long-running HTTP connections holding the old service worker in place.
I'm not sure that
let sw = await navigator.serviceWorker.register("/service-worker.js", {updateViaCache: "none"});
if (sw.waiting) {
sw.waiting.postMessage("SKIP_WAITING");
}
is the code that you want in this case. Your if (sw.waiting) check is only evaluated once, and the newly registered service worker might still be in the installing state when it's evaluated. If that's the case, then sw.waiting will be false-y at the time of initial evaluation, though it may be true-thy after a small period of time.
Instead, I'd recommend following a pattern like what's demonstrated in this recipe, where you explicitly listen for a service worker to enter waiting on the registration. That example uses the workbox-window library to paper over some of the details.
If you don't want to use workbox-window, you should follow this guidance check to see if sw.installing is set after registration; if it is, listen to the statechange event on sw.installing to detect when it's 'installed'. Once that happens, sw.waiting should be set to the newly installed service worker, and at that point, you could postMessage() to it.
Ok i had a similar issue and it took me two days to find the cause.
There is a scenario where you can cause a race condition between the new service worker and the old if you request a precached asset at the exact same time you call skip waiting.
For me i was prompting the user to update to a new version and upon their confirmation i was showing a loading spinner which was a Vue SFC dynamic import which kicked off a network request to the old service worker to fetch the precached js file which basically caused both to hang and get very confused.
You can check if your having a similar issue by looking at the service worker specific network requests (Network requests button in the image below) that are happening and make sure they aren't happening the instant you're trying to skip waiting on your newer service worker.

SignalR not handling requests after some limit.Tabs remains loading even to other browser on same or different machine

When number of tabs increases on browser for signalR implemented domain.The tab remains spinning after some limit of tabs.
From some reasearch it is said that it is the limitation of browser.The links are:
https://medium.com/yasser-shaikh/multiple-tab-issue-with-signal-r-9df76c1ffba0
https://github.com/SignalR/SignalR/issues/2744
https://github.com/SignalR/SignalR/issues/849
SignalR, Limited unique connections (opened tabs) IIS8, Windows8
But when I try to browse any url from same domain from different machine or from different browser, tabs are spinning on them too. the other machine tabs starts working as soon as I closed some tabs of the first browsers.
Please help
Thanks
The links that you have shared already describes the problem and also provided the answers.
For example "Using localstorage as a message bus between the tabs". This should fix the problem. For that purpose you can use the IWC-SignalR library from here: https://github.com/slimjack/IWC-SignalR if you want to reduce the work load.
Sample codes are as following:
var echoHub = SJ.iwc.SignalR.getHubProxy('echo', {
client: {
displayMsg: function (msg) {
console.log(msg);
}
}
});
SJ.iwc.SignalR.start().done(function () {
console.log('started');
echoHub.server.send('test').done(function () {
console.log('sent');
});
});
Here hub Echo with method Send defined on server. Method Send calls method displayMsg of all clients.
Then here is the displayMsg method:
var echoHub = SJ.iwc.SignalR.getHubProxy('echo', {
client: {
displayMsg: function (msg) {
console.log(msg);
}
}
});
echoHub.server.send('test');
The full implementation and the description is available on the above mentioned link.
Ya I have explored the solutions you have mentioned. And appplied it too. Now I am able to open multiple tabs with in my machine. However when I load multiple tabs on mine. It will block all other users on other machines. They will only be able to explore the URLS untill I close tabs on mine. it is blocking the block server when blocked by any user browser

Manually replaying requests queued by workbox-background-sync

I am working on offline support in my PWA app. I am using workbox for that. This is my current code:
const addToFormPlugin = new workbox.backgroundSync.Plugin('addToForm');
workbox.routing.registerRoute(
RegExp('MY_PATH'),
workbox.strategies.networkOnly({
plugins: [addToFormPlugin]
}),
'POST'
);
The code seems to works fine on my computer. However, once I run the app on the phone it takes ages to upload requests stored in IndexedDB. I know that it happens on the SYNC but it seems to take at least 5 minutes. This is not exactly what I need. I wonder if there is an option to access the IndexDB and send all the requests "manually" on click. Another way would be to check if the device is online. Here is how requests are stored:
If you need to force this, the cleanest approach would be to use the workbox.backgroundSync.Queue class (instead of workbox.backgroundSync.Plugin) directly.
The Plugin class takes care of setting up a fetchDidFail callback for you, so if you use the Queue class, you need to do that yourself:
const queue = new workbox.backgroundSync.Queue('addToForm');
workbox.routing.registerRoute(
RegExp('MY_PATH'),
workbox.strategies.networkOnly({
plugins: [{
fetchDidFail: async ({request}) => {
await queue.addRequest(request);
},
}],
}),
'POST'
);
You could then call queue.replayRequests() to trigger the replay, e.g., as a result of a message event:
self.addEventListener('message', (event) => {
if (event.data === 'replayRequests') {
queue.replayRequests();
}
});
But... that all being said, I think your best bet is just to let the browser "do its thing" and figure out when the right time is to replay the queued requests. That will end up being more battery-friendly for mobile devices.
If you're unhappy with the interval that the browser waits before firing a sync event, then the best course of action could be to open a bug against the browser—whether it's Chrome (as appears in your screenshot) or another browser.

ionic2 set cache view when triggering the button

<button class="alt-button" ion-item detail-none (click)="goToAbout()" clear small >
<ion-icon name='person' item-left></ion-icon>About us</button>
Button action
goToAbout() {
this.menu.close();
// close the menu and Goto About page
this.app.getRootNav().push(AboutPage);
}
api call
ionViewDidLoad(){
this.loading.present();
this.aboutservice.getPost().then(
response => {
this.items = response
this.loading.dismiss();
},
error=>{
this.error = error
this.showError('There was problem with server');
this.loading.dismiss();
});
}
it loads the api data everytime,but I want to load api data once and same button action i have used for sidemenu,Its working fine.please give any idea.
It seems strange behavior according to the doc here.
ionViewDidLoad
Runs when the page has loaded. This event only happens once per page
being created. If a page leaves but is cached, then this event will
not fire again on a subsequent viewing. The ionViewDidLoad event is
good place to put your setup code for the page.
But you can use it inside the constructor() as shown below.
constructor() {
//your Api call here
}

Resources