Как я могу перебрать объект jQuery и ждать события? - PullRequest
3 голосов
/ 24 марта 2020

Может ли кто-нибудь объяснить, как ждать, пока событие завершится sh, чтобы двигаться вперед на следующей итерации внутри для l oop? Например:

for ( i=0; i < item.length; i++ ) {
  $(video[i]).on('loadeddata', function() {
    // do my stuff
  })
}

Теперь с помощью этого кода я просто добавляю прослушиватель событий к каждому видео в правильном порядке, но, очевидно, они не будут загружаться таким образом. Они сделают другие мои вещи, когда они закончат sh загрузку, и потому что это непредсказуемо, это разрушит порядок показанного элемента на странице. Итак, как я могу заставить for l oop ждать, пока событие завершит свою работу, прежде чем оно перейдет к следующей итерации?

РЕДАКТИРОВАТЬ: я добавляю больше информации по запросу. У меня на самом деле есть объект, содержащий HTML элементов. Этот объект извлекается с var items = $('.db-gallery-item'). Значения этого объекта, как я уже сказал, являются <div> элементами, содержащими контейнер <div> с двумя элементами внутри для изображений (<img> и <a>) и один элемент <video> для видео. Загружая их, я должен следить за их порядком, поэтому требуется дождаться загрузки каждого элемента, чтобы сделать его видимым, и go работает над следующим.

решено: удалось решить это с помощью решения, предложенного пала sh. Это последний код, который я использовал.

if(i_length > 0) {
    (async function() {
        for (i = 0; i < i_length; i++) {
            var item = $(items[i]);
            if($(item).find('.dbg-video').length == 1) {
                var video = $(item[0]).children().children();
                if(video[0].readyState > 3) {
                    item.removeClass('db-are-unloaded');
                    $grid.masonry('appended', $(item));
                }
                else {
                    await new Promise(resolve => video[0].addEventListener('loadeddata', resolve));
                    $(item[0]).removeClass('db-are-unloaded');
                    $grid.masonry('appended', $(item[0]));
                }
            } 
            else if($(item).find('.db-gallery-image').length == 1) {
                await new Promise(resolve => $(item[0]).imagesLoaded().done(resolve));
                $(item[0]).removeClass('db-are-unloaded');                                          
                $grid.masonry('appended', $(item[0]));
            }
        }
    }());
};

Вот JSFiddle рабочий пример.

Ответы [ 2 ]

1 голос
/ 24 марта 2020

Вы можете использовать for..await logi c, например:

(async function() {
   for (i = 0; i < video.length; i++) {
      await new Promise(resolve => video[i].addEventListener('loadeddata', resolve));
      // do my stuff
   }
}());

Здесь итерация for-l oop будет ожидать завершения события loadeddata для video.

DEMO:

const fruitsToGet = ['apple', 'grape', 'pear']
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
const getNumFruit = (fruit, delay) => sleep(delay).then(v => fruit);

// Since getNumFruit returns a promise, we can await the resolved value before logging it.
const init = async () => {
  console.log('Start')

  for (let i = 0; i < fruitsToGet.length; i++) {
    const rand = Math.floor(Math.random() * 6) * 1000;
    const numFruit = await getNumFruit(fruitsToGet[i], rand)
    console.log(numFruit, 'delay: ' + rand)
  }

  console.log('End')
}
init()
0 голосов
/ 24 марта 2020

Вы можете создать массив функций, например:

var functions = [];
var index = -1;

function doMyStuff(currentIndex) {
    if (currentIndex = index + 1) {
        while ((index < functions.length) && functions[index]) {
            //Do something with $(video[index])
            index++;
        }
    }
}

for ( let j=0; j < video.length; j++ ) {
  $(video[j]).on('loadeddata', function() {
      functions[j] = true;
      doMyStuff(j);
  })
  functions[j] = false;
}

Объяснение: Мы используем переменную в виде блока для l oop, поэтому мы всегда будем знать, какое событие видео запущено. В конце l oop functions будет массив, содержащий только false элементов (событие еще не произошло), и при каждом событии мы сначала подтверждаем, какое событие произошло, а затем вызываем doMyStuff, который получает Индекс текущего элемента, где произошло событие. Если это следующий в очереди, то выполняется его функция и все последующие функции, событие которых уже произошло.

Менее привычный способ сделать это - применить цепочку обещаний, см. https://medium.com/@karenmarkosyan / как в управлении-обещаниям-Into-Dynami c -queue-с-vanilla- javascript -9d0d1f8d4df5

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