$scope.$apply not updating on page refresh - javascript

I have subscribed to signalr events. On notification updating textbox using $scope.$apply. Everything works fine. If page is refreshed using F5 or browser reload button, I am receiving signalr events but, textbox is not getting updated.
I am missing anything?
On notification
signalRHub.client.Notify = function (data) {
$scope.$apply(function () {
$scope.upgradeResult += data.Message;
});
}

What browser version are you using? If you are testing using IE, even the F5/Refresh would retrieve the cached page unless you change the settings under Internet Options->General tab->Browsing History subsection->Settings
By default- Check for versions of stored pages is selected as 'Automatic'. Modify this to 'Every time I visit the page' - this should bypass caching the page and changes made on the page should reflect. Although this may not resolve your impediment if caching is not the issue, but it is a useful tip to consider nevertheless to avoid caching problems.

Related

Angular 6: Trying to make synchronous call (delete) on browser close event (beforeunload/unload event of browser)

Actually, I want to update a flag in Db using a service call(Delete method) once the user close the browser. I am able to detect browser close action using onbeforeunload and onunload events but async call doesn't work for me(sometimes in debugging mode it works fine but on higher env it doesn't work).
Then, I tried to make sync request but then I found that Chrome now disallows synchronous XHR during page dismissal when the page is being navigated away from or closed by the user.
check link : https://www.chromestatus.com/feature/4664843055398912
I have tried new XMLHttpRequest() as sync, fetch api also Navigator.sendBeacon() but unfortunately nothing works for me.
Please suggest something which works because I have visited so many posts but nothing works for me.
Thanks in advance.
I have some solution for this. Hope so any one of them solves your issue.
constructor() {
window.onbeforeunload = ()=>{
//call API here
}
}
In your component constructor write above code
OR
In my opinion the better idea is making the heartbeat api that sends requests every N seconds to notify server that the session is active and the user is online. On the server check every M minutes if there was no heartbeat requests for more than N seconds: if it is so - execute the API request(what you wanted to execute on crash).
OR
'beforeunload' would be trigger when refreshing pages, closing tab, or closing the browser.
#HostListener('window:beforeunload', ['$event'])
beforeUnload(e: Event) {
e.returnValue = false;
}
OR
It is not possible to ensure that every time an user exits a browser page a specific function will be triggered. The reason is that the browser could close the window for many reasons. Yes it could be a user action but this is not the only case. For example The browser could crash.
In my case I will have to find another strategy to track the time the user stays on the page. For example I am planning to send a lot of API calls before the user exits with all the informations I need to understand his stay on the page. I will update the answer when I will reach a good solution. Anyway I will still wait for better answers.
You can use the fetch API.
The syntax would be:
fetch('API', {
method: 'POST', // Other opn are also supported like GET,PUT DELETE
body: '',
keepalive: true
});
Just an additional read:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API

How to stop a PWA from caching my website

I have a simple PWA, that I update and change from Github pages.
When I make an update to the website, It doesn't show on the devices using the website, because (at least I think) its being cached. I don't have any service workers to cache the site.
Even a normal refresh from the website (using all of these)
Doesn't refresh it and shows the changes. On iOS I manually have to go into settings and clear the website data to see the changes.
How can i fix this?
Use Network First (Network Falling Back to Cache)
https://developers.google.com/web/tools/workbox/modules/workbox-strategies#network_first_network_falling_back_to_cache
For requests that are updating frequently, the network first strategy is the ideal solution. By default, it will try to fetch the latest response from the network. If the request is successful, it’ll put the response in the cache. If the network fails to return a response, the cached response will be used.
When you make a page reload, a new check is done to verify if a new SW version is available.
However you need then to close all your app browser tabs in order to install the new service worker version.
In Chrome Dev Tools you can check the "Update on Reload" checkbox on the Application tab. This is useful for development.
I would suggest to read the Google docs about it.
Plus, if you want to learn more details about PWAs have a look at my articles.
UPDATE
The browser checks for updates automatically after navigations (at latest every 24h). However you can also trigger the update manually (for example you can have a timer and trigger it once per hour or according to your needs):
navigator.serviceWorker.register('/sw.js').then(reg => {
// ...
// Trigger this after your timeout
reg.update();
});
Alternatively you can use the updatefound event in order to detect in your code that a new sw version in available:
The onupdatefound property of the ServiceWorkerRegistration interface is an EventListener property called whenever an event of type statechange is fired; it is fired any time the ServiceWorkerRegistration.installing property acquires a new service worker.
navigator.serviceWorker.register('/sw.js').then(reg => {
reg.addEventListener('updatefound', () => {
const newSW = reg.installing;
newSW.addEventListener('statechange', () => {
// Check service worker state
if (newSW.state === 'installed') {
// A new SW is available and installed.
// You can update the page directly or better
// show a notification to the user to prompt for a page reload
// and inform about the new version available
}
});
});
});

How to force mobile browsers to reload the page when the application is reopened

As you may know, in chrome or firefox mobile, when you are visiting a webpage, if you close the browser and then open again, the first thing the app does is to open that webpage again, but it opens the version you left when you closed, so, for example if you're watching a forum thread with 4 posts and close, the next time you open you see the same thread with the same 4 posts even if there were new posts, the only way you can know is reloading the page.
I'm facing issues because my session variables expires but the page in a previous version is opened and then I get loads of notices due to the session variables not being defined.
I need to find a way to force the mobile browser to open a fresh instance of my page, so if the session variables already expired, the user is redirected to the proper page.
Thanks in advance.
If you use a library like axios, you can handle errors caused by your invalid session with interceptors and trigger a page reload programmatically.
axios.interceptors.response.use(function (response) {
return response;
}, function(error) (
if(error.statusCode === 401)
window.location.reload(); //or whatever
return error;
});

Notifications in javascript without user input

I've been trying to figure out a way to use notifications on a background process and couldnt find anything online about it. So, I figured out one way around it and wanted to share (Not sure if this is the best way to go about doing this but here goes:)
Problem: I want to notify the user of new info when the page is running but in the background (blurred). I could use alert('new info!'); to get the taskbar icon to flash, but then you have to manually dismiss it (tried it and it's hella annoying). I really liked the notifications, but they only work if the user performs an action, so not helpful...
I hope I won't be telling something stupid, but from where I see it (and remember from school) that's basically how http works : a request is sent to the server, which issues a response eventually after executing some server-side code.
Basically you're asking for a "PUSH" functionality from server to client, and in that case you can't make use of HTTP.
Some tricks exist to work around this limitation, but basically they're all issuing requests at a certain frequency (Dave's answer does exactly that). If your site doesn't change that much, that means a lot of requests are issued for no reason (nothing has changed), consuming bandwith for nothing.
From what I know, the answer to this is called Websockets, which are supported by recent browsers only. I never had the chance to use it though so I couldn't tell much more about it. This allows full duplex communication, thus allowing server to "push" data to the client. I guess that's what SO uses for "new message" notifications (top left of the screen - you see immediately when you receive a new message)
My solution: I made a chrome extension that runs in the background and triggers the notifications. It's a little limited in scope as you need to have chrome to do it, but it does what i need it to, and for the purposes of the problem i'm working on, i can just make my user group use chrome ;D
The specifics: The extension only has two components, the manifest and a script. Currently, i setup the manifest so that it only works on my site using the match identifier... and i set the permissions to include notifications.
The JS script has a window.setinterval that looks for an element in the page with the id NOTIFIER. If it's empty, it does nothing, otherwise it creates a notification based on the content and then clears the content to prevent showing the same notification multiple times... (I tried using .onchange for that element, but couldn't get the event to trigger... I'd prefer to do this on an event rather then setInterval)
Notify.js
function onExtLoad() {
var timer = setInterval(refresh,1000);
}
document.addEventListener('DOMContentLoaded', onExtLoad());
function refresh() {
if (document.getElementById('NOTIFIER').innerHTML == "") {
//do nothing?
} else {
var notification = webkitNotifications.createNotification("",
"You got a new message",
document.getElementById('NOTIFIER').innerHTML);
notification.show();
document.getElementById('NOTIFIER').innerHTML = "";
}
}
Then, all i need to do is have the JS on the page control when it adds info the the NOTIFIER and voila! notifications!
Hope this helps someone else.
#ExpertSystem: I messed around with the MutationObserver but I can only get it to trigger once. Here's a JSFiddle: http://jsfiddle.net/BTX8x/1/
Am I missing something? Is there a way to reset it?
EDIT: Figured it out, i needed subtree:true

Web Service Call in JavaScript Causing White Screen of Death (WSOD) in Browser

Here's the specs:
ASP.NET 3.5 using ASP.NET AJAX
AJAX Control Toolkit
jQuery 1.3.2
web services
IIS6 on Windows Server 2003 SP1
SP1 SQLServer 2005 SP3 Site is SSL
Infragistics Web Components 2009 Vol. 2 (using non-Aikido controls), UltraWebGrid and Tree control are main ones used.
Here's the problem:
I'm getting the White Screen of Death (WSOD) in IE 7/8. Basically, I have a page that has a left pane that has an AJAXControl Toolkit Accordion control where each accordion panes content is an Infragistics Tree Control. The right pane is a <div> that has an <iframe> whose content is reloaded based on what's clicked in the left menu pane.
In the <iframe>, a page with one or more UltraWebGrid controls loads up when you click on a menu item in the left pane. The grids all havea templated button column. When you click on the edit button of a grid row a popup window to edit the record is opened. This works fine for about ten times and then on the tenth time (sometimes earlier), the popup window opens with the correct URL in the address bar, but the page never loads.
We have an application that uses one popup window for updating records. Most of the time when you click on the [Edit] button to edit a record, the popup window opens and loads the update page. However, after editing records for a while, all of a sudden the popup window will open, but it stays blank and just hangs. The URL is in the address bar.
Loading up Fiddler I noticed that the request for the update page is never sent which leads me to believe it's some kind of lockup on the client-side. If I copy the same URL that's in the popup window into a new browser window, the page generally loads fine.
Observations:
- Since the request is never sent to the server, it's definitely something client-side or browser related.
- Only appears to happen when there is some semblance of traffic on the site which is weird because this appears to be contained within client-side code
- There is a web service being called in the background every few seconds checking if the user is logged on, but this doesn't cause the freeze.
I'm really at a loss here. I've googled WSOD but not much seems to appear related to my specific WSOD. Any ideas?
What the problem really is
So turns out the memory leaks (although I've sealed up some on the client-side) are not the issue. The issue is web service calls being made on the client-side. There is one that checks if a user is logged on every 4 seconds (to synchronize with another window) and then there are web service calls to get user preferences for a popup window and grid state. From what I've read, the web services have to be asynchronous. I assumed by calling them from JavaScript with success/fail callbacks that they were asynchronous but they really aren't. They're asynchronous from the client-side/browser point of view, but from the server-side, the call to the web service is made and returns when it is completed holding up any other operations since there is a limited number of connections.
So what is the easiest way to just make the web service methods asynchronous? Does the web service need to be converted to a WCF web service or can I use my existing ASP.NET web service call?
And for historical purposes, here's what I thought the problem was originally:
I wasn't able to reproduce this locally or on our testing servers. However, I got Fiddler to simulate modem speeds and all of sudden I can replicate the WSOD on my local PC. So it appears to be a slow or temporarily slow connection when opening a popup window that causes it to choke, at least in my test environment.
I did another test running IE without add-ons, iexplore.exe -extoff, but end up with the same result. I also fixed an issue where the iframe on the page was being recreated everytime the URL for the iframe changed. Part of my logic was omitted. Now the iframe is only created once. After that only the src attribute is updated when I want to load new content... my goof. I noticed some lingering window references in JavaScript closures, so now those are explicitly set to null in the closures when I'm done with them.
I've also done some memory leak investigation:
- As far as I can tell I do not have any circular references in the DOM and JavaScript or the other leak patterns mentioned here, http://www.ibm.com/developerworks/web/library/wa-memleak/?S_TACT=105AGX52&S_CMP=cn-a-wa
I've added the Crockenator's purge code for IE memory leaks (see http://www.crockford.com/javascript/memory/leak.html):
$(document).ready(function() {
function purge(d) {
var a = d.attributes, i, l, n;
if (a) {
l = a.length;
for (i = 0; i < l; i += 1) {
if (a[i]) {
n = a[i].name;
if (typeof d[n] === 'function') {
d[n] = null;
purgeCount++;
}
}
}
}
a = d.childNodes;
if (a) {
l = a.length;
for (i = 0; i < l; i += 1) {
purge(d.childNodes[i]);
}
}
}
$(window).unload(function() {
purge(document.body);
//alert("purge count: " + purgeCount);
});
});
None of my improvements have fixed the problem. in my local test scenario. Any ideas? Anyone? Anyone? Bueller?
Last Update
Thanks David for pointing out that it was session state causing the problems in the web services. "ASP.NET queues all requests to the same 'session'. So if the first request blocks for too long, it will hold up any other queued requests."
So what we ended up doing was try to minimize web services using session state but we also added the recommended settings by Microsoft for the number of connections, see http://msdn.microsoft.com/en-us/library/ff647786.aspx#scalenetchapt10_topic9
I think you may be having an issue with Session request synchronization. Have you marked your web service handlers as requiring session state?
ASP.NET queues all requests to the same "session". So if the first request blocks for too long, it will hold up any other queued requests. You can turn off session state for the page to avoid this and be truly asynchronous, however you will be unable to access session on the server, etc.
If you are using .ashx, you have to use an interface to get access to session state,the default is off, so check if you added one of these interfaces and remove if possible:
public class FooHandler : IHttpHandler, IReadOnlySessionState // readonly access
public class FooHandler : IHttpHandler, IRequiresSessionState // read-write access
If you are using an aspx page, it is on by default and you have to turn it off with a Page directive attribute:
<%# Page language="c#" Codebehind="WebForm1.aspx.cs"
AutoEventWireup="false" Inherits="WebApplication1.WebForm1"
EnableSessionState="false" %>

Categories