Javascript,本地存储问题。适用于台式机但不适用于移动设备

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

我正在为我的 Web 服务器后端使用 esp32 微控制器。 我使用模板处理器功能在后端构建页面,因为我不能使用超过 8 个套接字连接,因为 MCU 会崩溃。

为了更快地加载我的页面,我尝试在客户端的本地存储中保存一个相对较大的语言 JSON 文件。后端不知道它是否在客户端“缓存”,所以当我在本地存储中设置语言文件时,我用它设置了一个 cookie 以指示它已保存,因此后端知道缓存 json并且不会将其构建到页面中。

在后端,我检查是否有一个名为“cachedLang”的 cookie,它等于客户端的语言 ID。如“HU”或“EN”。如果此 cookie 等于实际的 clientLanguage cookie,则相同的语言文件会缓存在客户端,因此后端不必再次呈现它,而是将“useCached”字符串放入实际语言的位置 json渲染页面时。

客户端会检查它是否是字符串“useCached”,如果是,它会从本地存储中读取缓存的语言JSON并使用它。如果此字符串不是“useCached”,则它是一个 json 语言文件并使用它。

这在桌面上运行正常。但是在移动设备上,页面加载时没有 localStorage 和 Cookie。它只是空的,后端总是将巨大的语言文件渲染到 html 页面中。我也尝试了 IOS 和 Android。

后台代码如下:

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 %s\n", 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);
}

客户端代码如下:

<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>

在桌面上,语言文件将被呈现一次,从那时起客户端将从它的 localStorage 中提取它。如果客户端更改语言,“lang”cookie 将更改并且后端将发送适当的文件。但是在移动端,我好像没有localstorage?我在加载事件后尝试使用 setTimeout。尝试在页面加载后超时 250,500 毫秒(认为 localStorage 需要更多时间)但它不起作用。

非常感谢您的帮助。

这是一个错误。我之前做过这个 initLanguage();:

currentlang = getCookie("lang");

不检查 cookie 中是否有“lang”键。这覆盖了我的 currentLang 变量,js 将一个空的 currentLang 保存到 cookie 中。这就是我的后端读取空字符串的原因。 cookie 在那里,但它没有任何价值。

之所以在 Opera 和 chrome 中起作用,是因为它之前有一个带有密钥的 cookie,并且可以成功读取它。

所以我这样做了:

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

如果有 cookie,请读取它,如果没有,则设置它。 对不起我傻了。