Skip to content
Advertisement

Javascript, localStorage problem. Works on desktop but not on mobile

I’m using an esp32 microcontroller for my web server backend. I use a template processor function to build the page on the backend because i can’t use more then 8 socket connection because the MCU will crash.

In order to load my page faster, i try to save a relatively huge language JSON file on the client’s localStorage. The backend does not know if it is “cached” on client side so when i set the language file in local storage, i set a cookie with it to indicate that it is saved, so the backend knows about the cached json and does not build it into the page.

On the backend, i check if there is a cookie called “cachedLang” which is equal to the language ID for the client. Like “HU” or “EN”. If this cookie is equal to the actual clientLanguage cookie, the same language file is cached on the client side so the backend don’t have to render it again, instead it puts a “useCached” string into the place of the actual language json when rendering the page.

The client will check if it is the string “useCached”, if it is, it will read the cached language JSON from it’s localStorage and use it. If this string is not “useCached” then it is a json language file and using that.

This is working properly on desktop. But on mobile, there is no localStorage and no Cookie on page load. It’s just empty, and the backend will always render the huge language file into the html page. I tryed on IOS and Android too.

Here is the backend code:

boolean useCachedLang = false;
inline String mainPageTemplateProcessor(const String& var) {
    if (var == "LAN_OB") {
        if( !useCachedLang ){
            getLangFile();
            return String(currentLangFile);
        }else{
            return ""useCached"";
        }
    }
    return "";
}

static const inline void authenticateUser(AsyncWebServerRequest* request) {
    AsyncWebServerResponse* response;
    CLIENTLANG      = "HU";
    useCachedLang   = false;
    if (request->hasHeader("Cookie")) {
        AsyncWebHeader* allCookie = request->getHeader("Cookie");
        CLIENTLANG          = getCookie("lang", allCookie->value());
        String cachedLang   = getCookie("cachedLang", allCookie->value());

        // The following line will always print: "" "" if the page loaded from mobile.

        Serial.printf("Cached and client lang is %s %sn", cachedLang.c_str(),CLIENTLANG.c_str());
        
        if( cachedLang != "" && cachedLang == CLIENTLANG ){
            useCachedLang = true;
        }
        if (CLIENTLANG == "") {
            CLIENTLANG = "HU";
        }
    }
    response = request->beginResponse(LITTLEFS, checkPath(homePath), "text/html", false, mainPageTemplateProcessor);
    request->send(response);
}

Here is the client side code:

<script>
    window.addEventListener('load', (event) => {
      /* Wait for the load event. It does not matter if i put it directly or into 
      the load event. */
      initLanguage(~LAN_OB~);
    });

function initLanguage(newLangObj){
    if( newLangObj === "useCached" ){
        let storedLang = localStorage.getItem("cachedLang");

        // Tryed with window.localStorage too.

        if(storedLang){
            newLangObj = JSON.parse(storedLang);
        }else{
            langInited = true;
        }
    }
    if(!langInited){
        langInited      = true;
        currentLangObj  = newLangObj;
        cacheLanguage();
    }
}

function cacheLanguage(){

    /* This line will run on mobile and desktop too, but has no effect on mobile */
    localStorage.setItem(`cachedLang`, JSON.stringify(currentLangObj));
    setCookie(`cachedLang`,currentlang,365);

    try {
        localStorage.setItem('testLocalStorage', 'testLocalStorage');
        localStorage.removeItem('testLocalStorage');
        alert('supported');

        // Always alerts supported, on mobile and on desktop too

    } catch(ex) {
        alert('unsupported');
    }
}

</script>

On desktop, the language file will be rendered once, and from that point the client will pull it from it’s localStorage. If the client changes the language, the “lang” cookie will change and the backend will send the appropirate file. But on mobile, it seems to me that there is no localstorage? I tryed with setTimeout after the load event. Tryed with 250,500ms timeout AFTER the page loaded ( thiking that the localStorage need some more time ) but it does not work.

I appreciate the help.

Advertisement

Answer

It was a mistake. I did this before initLanguage();:

currentlang = getCookie("lang");

without checking if there is a “lang” key in the cookies. This overwrited my currentLang variable and the js saved an empty currentLang into the cookies. That’s why my backend read empty Strings. The cookie was there but it had no value.

The reason that this worked in opera and chrome is that it had a cookie with the key before and it could read it successfully.

So i did this:

if(getCookie("lang")){
    currentlang = getCookie("lang");
}else{
    currentlang = "HU";
    setCookie("lang",currentlang,365);
}

If there is a cookie, read it and if there isn’t then set it. Sorry i was silly.

Advertisement