JavaScript: избегайте мерцания при обновлении веб-страницы через веб-сокеты - PullRequest
0 голосов
/ 10 января 2020

Я создаю небольшое веб-приложение, которое включает веб-страницу, которая регулярно обновляется через веб-сокет. Каждое сообщение представляет собой строку, содержащую множество тегов HTML, включая код LaTeX. Содержимое этой строки помещается в контейнер div. Затем я использую renderMathInElement из KaTeX для интерпретации частей LaTeX.

Проблема: Это отлично работает для небольших сообщений, но для больших строк сайт запускается мерцание, при вставке нового контента. Мерцание возникает только в развернутой версии, что меня раздражает, потому что мой Firefox должен всегда выполнять код javascript с одинаковой скоростью. Тот факт, что время загрузки медленнее для развернутой версии, не должно изменять эффективность кода javascript.

Код

// connect the websocket
if (location.protocol == 'https:') {
    var socket = new WebSocket("wss://" + location.host + "/lectureserver", "lecture");
} else {
    var socket = new WebSocket("ws://" + location.host + "/lectureserver", "lecture");
}

var last = ""; // last message
var content = document.getElementById("lecture"); // div displaying content
var content_hidden = document.getElementById("lecture_hidden"); // hidden element to prepare content

socket.onerror = function (error) {
    console.log("unable to connect");
    content.innerHTML = "<p>Error. Can't connect!</p>";
};

socket.onmessage = function (event) {
    // check if data didn't change or is empty
    if (event.data == last || event.data == "") {
        return;
    }
    // save current vertical scroll position
    var scrollY = window.scrollY;
    // and old max height (to determine if client scrolled to the very bottom)
    var oldMax = document.body.scrollHeight - document.body.clientHeight;
    // save the received data
    var newContent = event.data;
    // fill the hidden element with the content
    content_hidden.innerHTML = newContent;
    // evaluate the math (KaTeX)
    renderMathInElement(content_hidden, {
        delimiters: [
            {left: "\\[", right: "\\]", display: true},
            {left: "\\(", right: "\\)", display: false},
            {left: "\\begin{align\*}", right: "\\end{align\*}", display: true},
            {left: "$", right: "$", display: false}
        ],
        macros: {
            "\\Q": "\\mathbb{Q}",
            "\\C": "\\mathbb{C}"
        },
        strict: false
    });
    // replace old content with now rendered and prepared new content
    content.innerHTML = content_hidden.innerHTML;
    // reset last content
    last = event.data;

    // keep window in place
    if (scrollY >= oldMax) {
        window.scrollTo(scrollX, 100000);
    } else {
        window.scrollTo(scrollX, scrollY);
    }
};

Как вы видите, я добавил скрытый div, который сначала подготавливает контент, а затем заменяет реальный content.innerHTML новым контентом. Но это изменение не решает проблему мерцания.

Если вам интересно, даже удаление части renderMathInElement не решит проблему. Мерцание происходит быстрее, но все еще присутствует.

Является ли интерфейс веб-сокета javascript каким-либо образом ленивым, что может привести к разнице между развернутым и локальным экземпляром? Если это строгое, не должно ли скорость траффи c иметь какое-либо значение, поскольку сообщение уже полностью передано, когда начинается обработка?

Пожалуйста, дайте мне знать, если вам нужны разъяснения.

...