Execute function at future date/time even if website not in use? - javascript

Any ideas as to how I can set a function up so that it runs in a week's time whether or not the app is in use at that time? So far I have thought of using window.setTimeout but that is obviously dependent on the current browser session (to my understanding). I've also thought of a while loop but it seems like that would be a messy solution.
Any help would be welcome. Thank you.

As soon as the browser loads another page or closes (tab or entirely), your script is stopped and get's unloaded.
Thus, you are unable to leave a "time bomb" for in a week, unless the user let's the page linger in the browser for that time at least.

The only solution to dispatch an event on the client is to use a ServiceWorker and a push notification, but this is a very new and not widely adapter solution.

Related

How to make setInterval work correctly in background tab

I'm using setInterval (within 3 Tampermonkey scripts) to check three different public websites every few seconds, so I can be alerted when specific text appears. These alerts are for freelance work offers, which can expire within seconds so I have to be quick.
It all works correctly, except when I'm working in a different tab or app, then that after about 6 minutes, setInterval starts to "trigger" for the background tab once per minute instead of once every few seconds.
Any suggestions how to fix this? Is it possible to use Date.now() in some way?
Note, I'm a complete beginner, willing to learn but need to keep things as simple as possible.
I've tried reloading the page every 3 minutes using window.location.reload() but that doesn't work. I guess I could create a script to activate and focus the tab every few minutes, but that would interrupt anything I was working on. I tested it with the following barebones script against https://www.google.co.uk/, in case something else in my script was causing a problem, but the same happens:
var i = 0;
setInterval(function() {
console.log("log: i:" + i);
i = i+1;
if(i==15) {
i = 0;
window.location.reload();
console.log("reloaded window");
}
}, 10000);
After a few minutes, i is incremented only once per minute - even following the window reload.
I've looked at this question
It mentions "workers" but can these be used within tampermonkey on public website I don't own? It also provides a link which suggests a workaround of playing an almost inaudible audio file - but I don't know if playing that within my tampermonkey script would work?
I see there are a number of workarounds here but I'm not sure if I can use any of them.
For example, can MutationObserver be used within a tampermonkey to detect changes in a public website? Even if it can, presumably I'd have to reload the webpage every time I needed to checK? Currently I'm using XMLHttpRequest instead of loading the webpage (far quicker and uses less CPU).
Interestingly, the above link seems to suggest that setInterval and SetTimeout are specifically targetted for throttling, I wonder if that means I could use some other function instead.
I've also seen this but I guess I can only use that for a website I own?
I can think of a few options.
Instead of having three scripts, use a single script, and run that single script on every site (with // #match *://*/*). Then, with that single script, set the interval. Whenever the interval callback runs, use Tampermonkey's GM_setValue and GM_getValue for cross-domain storage to coordinate executions - a callback will first check with getValue whether the last check was more than 3 minutes ago. If so, it calls setValue with the current date and performs the check. This way, even if the script is running on 100 different tabs (some in active tabs, some in background tabs), it'll still run the check once every few minutes.
To perform the check, use Tampermonkey's GM_xmlHttpRequest to get across same-origin restrictions; make a request to the three sites, and parse them into documents using DOMParser so you can programatically search through them for the elements you're looking for.
Perform the checks from a backend app instead of from a browser - for example, with Node and Puppeteer, which won't have throttling issues. To have the results be communicated with you, you could either have a userscript or websocket with your local webserver, or you could integrate the webserver into an Electron app instead. This is the approach I'd prefer, I think it's the most robust.
Use workers, which has worked for some

Make Angular Controller Run Continuously Through Page Refresh

In short, I am wondering if it possible to make an Angular controller pick up where it left off after the page is refreshed.
To give more details, suppose I have a controller that is responsible for running timers on several DOM items on that page. I click start, timer runs until I stop it. Now, when the page is refreshed, the timer and all values are re-set to zero. How could I make them continue from where they were immediately before the refresh event? In fact, is there a way to account even for the time it took for the page to refresh?
Currently, Angular is doing the timing. Should I try to switch timing to Node side?
Any advice is appreciated.
I strongly recommend that you try to switch the timer values to Node's side. That's the only way you can get the timers really updated and synchronized with your server.
I do not encourage that you store the timer values on storage, you will never have a reliable data, since the user can easily modify it.
Since there is no persistence of state between page loads in javascript you would need to store the timer state. localStorage would be one option
Not clear if timer is working towards a fixed time or tracking elapsed time. Store wht works best to allow you to reactivate when service runs again

Detemining time to screen for a web app

A web application has certain timeliness constraints. How can I check the time from invocation of a JS function to having the information visible in the browser?
Clearly I can start a stopwatch, but on what event should I stop it?
Modern browsers offer the Navigation Timing API, which you can use to get this kind of information. Which information from it you use is up to you, probably domComplete or loadEventStart (or, of course, loadEventEnd if you want to know when everything is fully loaded, but you could do that with window.onload). This tutorial may be useful.
If you're talking about requesting something via ajax after page load (you've said "...from invocation of a JS function to having the informatin visible in the browser..."), adding that to the page, and seeing how long that took, you'd stop the timer after you were done appending the elements to the DOM, immediately before returning from your ajax onreadystatechange handler callback. Or if you want to be really sure the information has been rendered, after using setTimeout(function() { /*...end the timer...*/ }, 0); from that callback instead, which yields back to the browser for the minimum possible time, giving it a chance to render (if it doesn't render while JS is running).

Meteor: Check how many clients are subscribed to a certain publish function

Is there a way of checking the number of currently subscribed clients to a certain publish function? Problem is that I have different groups where every group has its own unique ghash.
When a user chooses to leave a group and enters a new one, this ghash changes and THE SAME publish function is subscribed, although with a different ghash of course.
So I am looking for a way to check how many clients are subscribed to each group/ghash at a time (at the server side). I've been fiddeling around all day with stuff like this but it does not work that well to be honest. I am also listening for the "unsub" event of sockets and all that but still ... this is all buggy as hell.
If some one's interested in my whole code, you can find it here! (I found it too long to paste it here into my post.)
I really hope someone can help! :-)
cheers, P
EDIT: Or in other words: Is there a way to count the number of clients currently connected to a sockjs websocket where all these websockets were called with the same params?
=========================================================================
EDIT 2:
New version: LINK
For some reason this is not working at all ... No inserts are made because the ghash provided to the subscription is NEVER equal to any of the actual socket subscriptions (--> see lin 20: ghash is never equal to ghash2). I just don't understand how this is possible? the whole subscription function is called each time the Session ghash changes. How can this var never be equal to the param submitted to the actual socket (submission)? (it's always also a ghash, but always a ghash of another group).
I am really lost here! :-(
I now see you are doing straight old node style socket.io programming. I've done similar things in node projects. This is maybe the real question. On the docs for Meteor they don't even use the word socket. Maybe someone else would get into that new question with you, but this question about tracking subscribers is answered by this answer.
I think meteor is a new world, and will handle such stuff for you, if you adapt to its way of thinking. For example, make a collection of messages, with a field for chatroom. Each client picks their chatroom, finds those messages.find({chatroom:'box5'}), and displays them. A new message automatically goes to every client that is listening to that chatroom. Let Meteor use sockets for you.
Answer to counting clients subscribed to something:
Pseudo code:
Make an object to hold the counts of each subscription signature
counts = {}
on signup, Make a string that represents the subscription uniquely, add it to your counting object.
counts['params as string'] += 1;
on signout
counts['params as string'] -= 1;
The logic to know when no one is still subscribed is this:
done = (0 == counts['params as string'] )
Apparently as I know as of now it is not possible to do this.
I did some research and tried many things but for some reason sometimes multiple websockets are opened for trasnfering the same data to the same client. --> counting the number of clients connected is impossible via this approach.
Just triggering an event when my ghash changes is also not good enough as a close of the browser window would not trigger it.
I think having a functionality to count the number of clients "viewing the same data changes" (can't think of a better way to put it) would be awesome. Maybe some meteor core dev can just put his/her 2 cents in here so we know if this is even possible at all.
I hope someone can come up with a solution at some point .. I can't! :(
My user-status package tracks the number of clients connected to a Meteor app by tracking the number of subscriptions to a global publish function. You may be able to draw some inspiration from it. It's not granular at the per-publication level, but you can certainly do the same thing for publications that you are interested in.
https://github.com/mizzao/meteor-user-status
The main points to note are
each open session will call the subscription (users may have more than one tab open)
each time a user logs in our out, the subscription will update
you can read the per-session id in the publish function
you can listen to the close event for the SockJS socket for browser tabs being closed, etc.
I don't think it would be too hard to do this for groups; I am doing the same thing for another project.

How can I have a JS script update a page for everyone viewing it?

I'm creating a web application that allows users to make changes through Javascript. There is not yet any AJAX involved, so those changes to the DOM are being made purely in the user's local browser.
But how can I make those DOM changes occur in the browser of anyone else who is viewing that page at the time? I assume AJAX would be involved here. Perhaps the page could just send the entire, JS-modified source code back to the server and then the other people viewing would receive very frequent AJAX updates?
Screen sharing would obviously be an easy work-around, but I'm interested to know if there's a better way, such as described above.
Thanks!
You are talking about comet, for an easy implementation i'd suggest:
http://www.ape-project.org/
and also check these:
http://meteorserver.org/
http://activemq.apache.org/ajax.html
http://cometdaily.com/maturity.html
and new html5 way of it
http://dev.w3.org/html5/websockets/
Hope these help.
Max,
Ajax will have to be involved. If i may, I'd like to suggest jQuery as a starting point for this (i know you didn't tag as such, but i feel it'd be appropriate, even if only to prototype with). the basic semantics would involve running the ajax request in combination with a setInterval() timer to fire off the ajax request. this could be done in jQuery along the lines of:
$(document).ready(function() {
// run the initial request
GetFreshInfo();
// set the query to run every 15 seconds
setInterval(GetFreshInfo, 1500);
});
function GetFreshInfo(){
// do the ajax get call here (could be a .net or php page etc)
$.get('mypageinfostuff.php', null, function(data){$('#myDivToUpdate').html(data);});
}
that's the basic premise... i.e the webpage is loaded via GetFreshInfo() initially straight away, then it's requeried every 15 seconds. you can add logoc to only refresh the div if there is new data there, rather than always updating the page. as it's ajax, the page won't freeze and the process will be almost invisible to the user (unless you want to flag the changes in any way)
Hope this helps
jim

Categories