javascripthtmlyepnope

How to use a preloader to load an external javascript if Internet becomes available after startup?


I've been experimenting with responsive voice for my html5 application. Apart from responsive voice, my app works stand-alone, with no need for the Internet, because the schools where I work have unreliable Internet connections.

I previously had a problem waiting for RV's javascript to load on a slow connection, which I solved using the preloader yepnope:

yepnope({
    load: 'https://code.responsivevoice.org/responsivevoice.js',
    callback: function (url, result, key) {
        if (typeof responsiveVoice!="undefined"){
                //code to activate RV functionality here
        }
    }
});

While testing this out, I realised the potential for something much better: yepnope automatically times out after 10 seconds if the script doesn't load and triggers the callback function anyway. That timeout can be changed, but what I'd like is, effectively, no timeout at all!

For example, if the students start using my app at 07:30 a.m. when the school's satellite dish barely works, then at 3 p.m. the clouds clear to make RV viable, it would be nice if the script finally loaded, triggered the callback and RV sprang into life.

So I have 3 questions:

  1. In principle, is there any reason why I should not change the yepnope timeout from 10 seconds, to 12 hours? e.g.

    yepnope.errorTimeout = 43200000;
    
  2. I notice that yepnope has been deprecated. Can anyone recommend a similarly easy-to-use preloader with a no timeout option?

  3. Would it be lighter on system resources to use setInterval? e.g.

    var net_check = window.setInterval(yepnope, 18000); // try loading the script every 5 minutes
    

    then if RV loads, cancel the setInterval:

    yepnope({
      load: 'https://code.responsivevoice.org/responsivevoice.js',
        callback: function (url, result, key) {
        if (typeof responsiveVoice!="undefined"){
            clearInterval(net_check);
            //code to activate RV functionality here
        }
      }
    });
    

Thanks as always for any advice.

Edit: @Steyn van Esveld raised a really good point: "Is there any reason you can't download the responsivevoice.js and load it locally?"

In fact the RV script doesn't provide the text-to-speech voices itself - it's more of a facilitator. If your browser has native t-t-s support, it will use it, if not, they generate audio files (presumably from their website) and send them to your browser. Also, even Chrome's native t-t-s support evaporates if you are off-line. e.g. if you run:

voices = window.speechSynthesis.getVoices();
voices.length

from the console when offline, it returns "0".

This means I need a fallback if the Internet goes down after my app loads. The most reliable way I've found to do this is:

var rvStarted=false;
responsiveVoice.speak(vocEx, {onstart:function(){rvStarted=true;}}); 
setTimeout(function(){
  if (rvStarted==false){
    responsiveVoice.cancel();
    audVoc.play(); //plays a backup off-line recording 
  }
},1000);

There is an onerror callback in the RV api, but it's vaguely documented, and I certainly cannot control the timeout myself as I can with this script.


Solution

  • After more research and experimenting, I've got a solution that works. If anyone can come up with something more efficient, I'd be delighted. First the code (explanation follows):

        function loadRV() {
        console.log("Trying to load RV");
        inject.js('https://code.responsivevoice.org/responsivevoice.js',           
            function() {
                if (typeof responsiveVoice!="undefined"){
                    clearInterval(net_check);
                    console.log("RV loaded");
                    // code here to turn on RV functionality
                }
                else {
                    console.log("RV load failed");
                }
            });
        }
    
        var net_check=setInterval(function(){
            loadRV();
        },60000);
        loadRV();
    

    Now the explanation:

    1. I realised that yepnope detected that there was no network connection during the first try, and thereafter made no attempt to load the javascript despite the network having been meanwhile turned on. The problem was not about timeout (thus the change in the question title.
    2. So I searched around for a replacement for yepnope that would try to load the javascript each time it was called regardless of what had previously happened. I eventually came across inject.js. This is based on yepnope with some functionality removed and some added. I guess the ability to check if there is a network connection was removed, which suited my needs.
    3. I then wrapped inject.js in a function and called it every minute with setInterval. I also call it once immediately so that RV functionality will be present if there is a viable Internet connection at initialisation.

    Although this seems unwieldy, it's working very well so far. I've tested it with the three situations that I commonly face:

    1. No network connection at all during startup; the computer connects to the network some time later.
    2. A local network connection but no Internet connection during startup; the local network connects to the Internet some time later.
    3. A very slow Internet connection during startup; the connection becomes viable some time later.

    The setInterval has no appreciable effect on program execution, and the added functionality is quite transparent. If I connect the computer to the network and start a listening activity, about 1 minute later the RV voices will be added to my off-line recordings.

    I doubt that many others face similar problems (I certainly would not wish them on anyone), but if so, I do hope this helps.