Угловой обещает последовательный цикл


У меня есть следующий набор данных.

 $scope.orders = [
        { material: 'A', quantity: 32, orderNumber: 'dummy'},
        { material: 'A', quantity: 65, orderNumber: 'dummy'},
        { material: 'A', quantity: 86, orderNumber: 'dummy'},

        { material: 'B', quantity: 45, orderNumber: 'dummy'},
        { material: 'B', quantity: 68, orderNumber: 'dummy'},
        { material: 'B', quantity: 15, orderNumber: 'dummy'},

        { material: 'C', quantity: 11, orderNumber: 'dummy'}
    ];

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

Итак, я ищем что-то вроде этого:

Материал а: заказ 1 - > заказ 2 - > заказ 3 - > материалран

Когда материал из A будет готов, начните материал B

B материал: приказ 1 -приказ 2 -приказ 3 -> materialRun

Когда материал из B будет завершен, начните материал C

...

Мне также нужен результат от каждого createOrder для обновления списка заказов

Сейчас я использую угловые обещания, но я открыт для предложений. Я надеюсь, что эта скрипка помощь: http://jsfiddle.net/a1sp0ye2/

2 3

2 ответа:

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

/**
 * Loop the items array asynchronously.
 *
 * @param items - Array to iterate
 * @param doLoopBody - Callback that executes the body loop, returns promise
 */
function asyncLoop(items, doLoopBody) {
    var i = 0, d = $q.defer();

    nextIteration();

    return d.promise;

    function nextIteration() {
        if( i < items.length ) {
            doLoopBody(items[i], i, items).then(
                function() {
                    i++;
                    nextIteration();
                },
                onError
            );
        }
        else {
            d.resolve();
        }
    }

    function onError(reason) {
        d.reject(reason);
    }
}

Исходя из этого, здесь является грубой реализацией вашего случая (смотрите консоль браузера для вывода).

Я не уверен, что это может вам помочь, но попробуйте использовать мой код: jsfiddle

        $scope.promises = [];
        ordersByMaterial.forEach(function(order) {
            $scope.promises.push(createOrder(order));
        });

Я попытался проверить его, создав $scope.logsCreateValue = [];, где я храню случайные значения из Math.floor(Math.random() * 10); смотрите в console.log($scope.logsCreateValue);, он должен совпадать со значениями из $scope.orders[key].orderNumber = res[key].orderNumber;