0

Here is my code:

mylabel:{
    var myTimeout = setTimeout(function(){
      SpinnerDialog.hide();
      alert("Timeout");
      break mylabel;
    }, 10000);
    connectWifi();
  }

I have a function connectWifi() that can hang if the Wi-Fi network is not available so I want to stop it after a fixed amount of time. This function contains other functions, it does something like this:

function(){
    function(){
      function(){

      }
    }
  }

When the timeout fonction is called I get an error saying "Undefined label"

EDIT: My goal is not to stop the timeout function is to stop the connectWifi function.

if you want to see the connectWifi() function here is the code (I'm using the following cordova plugins : WifiManager, autowifi and CordovaMqTTPlugin):

    function connectWifi() {
  cordova.plugins.WifiManager.isWifiEnabled(function (err, wifiEnabled) {
    console.log("isWifiEnabled result : " + wifiEnabled);
    if (wifiEnabled == false) {
      cordova.plugins.WifiManager.setWifiEnabled(true, function (err, succes) { console.log(err, succes); });
      console.log("-- Wifi Enabled --");
    }
  });
  window.plugins.autowifi.setssid(s_SSID, s_PASS);
  SpinnerDialog.show(null, "Connexion en cours...", true);
  window.plugins.autowifi.connect(function (scc) {
    wifiReady = true;
    SpinnerDialog.hide();
    console.log("Wifi connected");
    console.log("debut fonction connectMQTT");
  if (wifiReady) {
    //Connexion MQTT
    SpinnerDialog.show(null, "Acces au serveur en cours...", true);
    cordova.plugins.CordovaMqTTPlugin.connect({
      url: _url, //a public broker used for testing purposes only. Try using a self hosted broker for production.
      port: _port,
      clientId: _clientId,
      success: function (s) {
        alert("Connexion reussie !");
        connected = true;
        console.log(JSON.stringify(s));
        document.getElementById("connect").style.display = "none";
        document.getElementById("disconnect").style.display = "initial";
        document.getElementById("activity").innerHTML += "--> Success: you are connected to, " + _url + ":" + _port + "<br>"
        SpinnerDialog.hide();
        SpinnerDialog.show(null, "Recuperation des donnees...", true);
        //Abonnement MQTT au topic
        cordova.plugins.CordovaMqTTPlugin.subscribe({
          topic: _topic,
          qos: 0,
          success: function (s) {
            SpinnerDialog.hide();
            document.getElementById("activity").innerHTML += "--> Success: you are subscribed to the topic, " + _topic + "<br>"

            cordova.plugins.CordovaMqTTPlugin.listen(_topic, function (payload, params, topic, topic_pattern) {
              //params will be an empty object if topic pattern is NOT used. 
              document.getElementById("activity").innerHTML += "--> Payload for" + topic + " topic: " + JSON.stringify(payload) + "<br>"
            })
          },
          error: function (e) {
            SpinnerDialog.hide();
            document.getElementById("activity").innerHTML += "--> Error: something is wrong when subscribing to this topic, " + e + "<br>";
            document.getElementById("subscribe").style.display = "initial";
            document.getElementById("unsubscribe").style.display = "none";
            //alert("err!! something is wrong. check the console")
            console.log(e);
          }
        });
        //---------------------

      },
      error: function (e) {
        SpinnerDialog.hide();
        connected = false;
        //document.getElementById('status').innerHTML = "déconnecté";
        //document.getElementById('statusbar').className = "w3-bar w3-red"
        alert("Echec de la connexion, assurez-vous que vous êtes connectés en wifi au serveur puis veuillez reessayer");
        document.getElementById("activity").innerHTML += "--> Error: something is wrong,\n " + JSON.stringify(e) + "<br>";
        document.getElementById("connect").style.display = "initial";
        document.getElementById("disconnect").style.display = "none";
        alert("err!! something is wrong. check the console")
        console.log(e);
      },
      onConnectionLost: function (e) {
        SpinnerDialog.hide();
        console.log(JSON.stringify(e));
        connected = false;
        //document.getElementById('status').innerHTML = "déconnecté";
        //document.getElementById('statusbar').className = "w3-bar w3-red"
        alert("Vous avez ete deconnecte");
        document.getElementById("activity").innerHTML += "--> You got disconnected";
        document.getElementById("connect").style.display = "initial";
        document.getElementById("disconnect").style.display = "none";
      }
    });
    //--------------------
  } else {
    console.log("wifiReady false");
  }
  });
}

(Few things are in french because I'm french)

Alban .L
  • 13
  • 6
  • Your goal isn't clear. What would be the purpose of that `break` ? – Denys Séguret May 22 '18 at 08:35
  • 1
    You break out of loops, not from functions. – FINDarkside May 22 '18 at 08:37
  • @Alban do you want to stop the timeout function? – Abdul Qayyum May 22 '18 at 08:37
  • Possible duplicate of [How to stop a setTimeout loop?](https://stackoverflow.com/questions/8443151/how-to-stop-a-settimeout-loop) – Nope May 22 '18 at 08:40
  • Could you please show us the code inside `connectWifi` ? – Jonas Wilms May 22 '18 at 08:42
  • 1
    I edited my post to add more informations. I don't know if it answer your questions @FINDarkside https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label It say that we can use a break to exit a labeled block – Alban .L May 22 '18 at 08:44
  • The break occurs in an anonymous function that is declared in the labeled statement, but is itself not part of the statement. So, you cannot use the label from the anonymous function. – NineBerry May 22 '18 at 08:45
  • This is an [XY Problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). You need to work with whatever API `connectWifi` uses to determine timeouts or set flags – charlietfl May 22 '18 at 08:46
  • What function exactly is hanging? `CordovaMqTTPlugin.connect` for example already has an optional `connectionTimeout` parameter that you are currently not using. – NineBerry May 22 '18 at 09:03
  • Here I was doing a test to connect to a wifi network that doesn't exist so I was stuck (deliberately) at window.plugins.autowifi.connect(). I would like to stop trying to connect to a network after 10 seconds. – Alban .L May 22 '18 at 09:06
  • Looking at the source code of the autowifi plugin, it does not offer any other way to stop the connect() method but a successful connection or an Android exception being thrown by the system. If you want to be able to use a timeout for the connect method, you have to change the source code of the autowifi plugin itself. – NineBerry May 22 '18 at 09:20

2 Answers2

1

Instead of having a huge block of code, lets divide it into small reusable promising pieces:

function promisify(fn) {
  return function() {
    return new Promise((resolve, reject) => {
     fn((err, res) => err ? reject(err) : resolve(res));
    });
  }
}

const isWifiEnabled = promisify(cb =>  cordova.plugins.WifiManager.isWifiEnabled(cb));    

const enableWifi = promisify(cb => cordova.plugins.WifiManager.setWifiEnabled(true, cb));

const connect = options => promisify(cb => cordova.plugins.CordovaMqTTPlugin.connect({
  ...options,
  success: res => cb(null, res),
  error: cb,
})();

Now that weve got promises, we can easily chain them and work with them:

async function ensureWifi() {
  if(!await isWifiEnabled()) await enableWifi();
}

To implement a timeout, we just use Promise.race:

function cancelAfter(promise, time) {
  const timeout = new Promise((_, reject) => setTimeout(reject, time, new Error("Timeout")));
  return Promise.race(promise, timeout);
}

So we can do:

(async function() {
  try {
    // show loaders here
    await cancelAfter(ensureWifi(), 1000);
    await cancelAfter(connect({ /*...*/ }), 200);
    // All done
 } catch(error) {
    // Api error or timeout
 }
})()
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • I'm not sure to understand everything but your answer is intresting. Could you explain this bit of code ? `async function ensureWifi() { if(!await isWifiEnabled()) await enableWifi(); }` Does it wait WifiEnabled() to be false to activate wifi ? – Alban .L May 22 '18 at 09:28
  • @alban yes exactly. – Jonas Wilms May 22 '18 at 13:37
  • 1
    you need to fix the argument to Promise.race, it is an array: Promise.race([promise, timeout]); – Arthur Ronconi Jan 23 '23 at 12:59
0

The break occurs in an anonymous function that is declared in the labeled statement, but is itself not part of the statement. That is why you cannot jump to the label from the anonymous function.

Some questions that discuss your actual problem (How to cancel an activity from a timer):

You will see that there is no easy built-in way at this point in time.

NineBerry
  • 26,306
  • 3
  • 62
  • 93