Design Pattern, чтобы избежать позднего возврата обещаний, перезаписывающих более быстрые? - PullRequest
0 голосов
/ 02 мая 2018

Я разбираюсь в том, как избежать нежелательного поведения при загрузке изображений с помощью обещаний. Мое реальное использование довольно сложное (большое приложение trijs), поэтому я свел мою проблему ниже к более простому объяснению.

У меня есть галерея div, которая показывает изображение. Есть группа миниатюр, которые пользователь может щелкнуть, чтобы загрузить изображение, связанное с этим миниатюрой, и после загрузки показывает его в галерее div (в реальном приложении здесь используется обещание, так как мы должны загрузить изображение, а затем после загрузки создать текстуру перед передачей этой текстуры для применения к плоскости).

Проблема, с которой я столкнулся, заключается в том, что если пользователь быстро щелкает несколько миниатюр, они применяются к элементу галереи в порядке их загрузки, что может означать, что пользователь может щелкнуть большое изображение для загрузки, а затем маленькое изображение, что приведет к маленькое изображение показывается, но затем перезаписывается большим изображением (даже если оно не было выбрано последним из-за того, что оно больше и поэтому загружается дольше).

Я не знаю, как изящно решить эту проблему, и надеюсь, что кто-то сможет подсказать, как другие программы / программы решают эту проблему. Это так же просто, как иметь систему резервирования, чтобы увидеть, выбрано ли изображение после загрузки, а если нет, то прервать?

1 Ответ

0 голосов
/ 03 мая 2018

Существует ряд различных алгоритмов для решения этой проблемы, и часть процесса выбора зависит от того, какое именно поведение вы хотите. Исходя из вашего описания, звучит так, будто вы хотите, чтобы изображение отображалось сразу после загрузки, но никогда не перезаписывало изображение, которое появилось после него и уже было отображено. Это означает, что если изображения запрашиваются в порядке 1,2,3, но поступают в порядке 2,1,3, то вы будете показывать изображение 2, затем 3 и никогда не показывать 1.

Если предположить, что это желаемый алгоритм, то довольно простой способ сделать это - просто назначить каждому запросу порядковый номер и просто отслеживать последний порядковый номер, который вы показали. Всякий раз, когда какое-либо изображение завершает загрузку, вы проверяете, является ли его порядковый номер выше последней отображаемой последовательности. Если нет, вы не показываете его, потому что это старое изображение, которое превзошло новое изображение. Если это так, то вы показываете его и обновляете номер lastShownSequence до порядкового номера этого изображения. Для этого типа алгоритма требуются две устойчивые переменные для отслеживания номера lastShownSequence и номера nextSequenceNumber.

Вот пример реализации кода:

var lastShownImage = 0;
var nextSequenceNumber = 1;

// url is image url
// elem is image element in the page to replace with newly loaded image element
function loadImage(url, elem) {
    let imageSequenceNumber = nextSequenceNumber++;
    let img = new Image();
    img.onload = function() {
        // image loaded now
        // see if we should display it or not
        if (imageSequenceNumber > lastShownImage) {
            // hide current image so there's never any flashing of two images
            elem.style.display = "none";
            // record the sequence number we are showing
            lastShownImage = imageSequenceNumber;
            // insert new image
            let parent = elem.parentNode;
            parent.insertBefore(img, elem);
            // remove previous image
            parent.removeChild(elem);
        }
    };
    img.src = url;
}

Если вы не хотите, чтобы lastShownImage или sequenceNumber были открыты, как эта, то их можно инкапсулировать либо в IIFE, либо в экземпляр класса, который вы создаете, но, поскольку я не вижу как именно вы будете использовать это в своем коде или посмотреть, нужна ли вам более обобщенная реализация с несколькими экземплярами, я не добавил для этого никаких дополнительных усложнений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...