Как дождаться завершения всех функций запущенных в цикле $each

У меня такой код:

getFilms() {
    $.each(filmArray, (index, item) => {
        this.homeService.getFilmInfo(item, async (result) => {
            this.moviesRenderer.renderMovies(result);
        });
    });

    // add click handlers for moies list
    this.productService.addMovieHandlers();
}

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

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

Я также записывал каждую запущенную функцию в список Promise, а затем ожидал их завершения с помощью Promise.all, но это тоже не сработало, метод также завершился до завершения всех функций. Подскажите пожалуйста, как мне дождаться завершения всех запущенных в цикле функций.

Пробовал async/await и Promise так:

getFilms() {
    let promises = [];

    $.each(filmArray, (index, item) => {
        promises.push(new Promise(() => {
            await this.homeService.getFilmInfo(item, async (result) => {
                await this.moviesRenderer.renderMovies(result);
            });
        }))
    });

    Promise.all(promises).then(values => {
        // Do work
    });
}

getFilmInfo(path, callback) {
    $.get(path, (result) => {
        callback(result);
    });
}

Ответы (1 шт):

Автор решения: Grundy

Так как функция getFilmInfo не возвращает Promise ее нельзя дождаться с помощью await.

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

  1. вызов первого переводит Promise в success состояние
  2. вызов второго переводит Promise в error состояние

Таким образом код обертки может выглядеть так:

new Promise(resolve => this.homeService.getFilmInfo(item, resolve))

Теперь можно, можно работать с результатом, как с Promise

В итоге получится следующее:

async getFilms() {
    var itemsPromises = $.map(items, async (item) => {
        var result = await new Promise(resolve => this.homeService.getFilmInfo(item, resolve));
        this.moviesRenderer.renderMovies(result)
    });
    
    await Promise.all(itemsPromises);
    
    // Do work
}
→ Ссылка