JS Дождаться нескольких событий в функции для завершения

0

У меня есть функция, которая загружает изображения и отображает их на странице. Как сделать, чтобы дождаться завершения функции?

$("#images").change(function(){
        updateArray(this);
        addImages();
    });

function updateArray(inp)
    {
        for(var i=0,file; file = inp.files[i]; i++)
        {
            var reader = new FileReader();
            reader.onload = function (evt)
            {
                images[images.length] = evt.target.result;
            }
            reader.readAsDataURL(file);
        }
    }

Я хочу вызвать addImages() после завершения всех событий в updateArray()

  • 1
    Что такое updateArray ? Это синхронно? Асинхронный? Мы не можем помочь вам без определения функции updateArray .
  • 0
    Можете ли вы показать нам код функции updateArray? Как правило, вы достигаете этого с помощью обратных вызовов в JS.
Показать ещё 1 комментарий
Теги:
events

2 ответа

4
Лучший ответ

Я бы использовал jQuery отложенные/обещания здесь. Это позволит вам подождать, пока каждая onload будет завершена, а затем вызовет обратный вызов.

Вот пример:

function updateArray(inp)
{
    var promises = [];
    for(var i=0,file; file = inp.files[i]; i++)
    {
        var reader = new FileReader(),
            d = new $.Deferred();

        promises.push(d);
        // Make sure we "capture" the correct 'd'
        (function(d){
            reader.onload = function (evt)
            {
                images.push(evt.target.result);
                d.resolve();
            }
        }(d));
        reader.readAsDataURL(file);
    }

    return $.when.apply($, promises);
}

Это создаст новый отложенный объект для каждого FileReader. Когда каждый заканчивается, его соответствующие отсрочки будут разрешены. $.when используется для объединения всех отложенных в один. Итак, в вашем .change() вы можете просто сделать это:

$("#images").change(function(){
    updateArray(this).done(function(){
        addImages();
    });
});

PS Вы также можете передать параметры для resolve() которые будут использоваться в .done(). Итак, вместо добавления к массиву images вы можете сделать d.resolve(evt.target.result); ,

(function(d){
    reader.onload = function (evt)
    {
        d.resolve(evt.target.result);
    }
}(d));

Затем в .done() вы можете сделать:

$("#images").change(function(){
    updateArray(this).done(function(){
        // Each '.resolve' added a new parameter to here, let get them all
        images = [].slice.call(arguments, 0);
        addImages();
    });
});
  • 1
    Я не знаю , что images должно быть, но я хотел бы предложить , чтобы отменить его и использовать d.resolve(evt.target.result) вместо - получение images в результате возвращенного обещание.
  • 0
    @ Берги: Неплохая идея :-)
1

Есть несколько способов, по которым вы можете приблизиться к этому, однако, если вы используете jQuery (который, как вам кажется), я бы рекомендовал изучить обещания (см.: http://api.jquery.com/promise/).

Они представляют собой более современную парадигму для отложенных обратных вызовов, которые имеют некоторую семантическую обработку для выполнения функций, основанных на успешном завершении, сбое и тех, которые будут всегда обрабатываться.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню