Stvenoo
Stvenoo

Reputation: 67

Angular Promises Sequential loop

I have the following set of data.

 $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'}
    ];

I want to process (createOrder) the orders grouped by material. After all the orders for that particular material have been processed I want to call another function (materialRun) that does a material run. After this function is successful the next material (with its corresponding orders) has to be processed etc.. All these calls have to be sequential because the backend cannot process everything in parallel.

So i'm searching for something like this:

material A: order 1 -> order 2 -> order 3 -> materialRun

when the materialRun from A is done, start material B

material B: order 1 -> order 2 -> order 3 -> materialRun

when the materialRun from B is done, start material C

...

I also need the result from each createOrder to update the orders list

I'm using angular promises for now but i'm open for suggestions. I hope this fiddle helps: http://jsfiddle.net/a1sp0ye2/

Upvotes: 3

Views: 442

Answers (2)

Oleksii
Oleksii

Reputation: 328

I'm not sure that is can help you, but try to use my code:jsfiddle

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

I tried to test it by creating $scope.logsCreateValue = []; where I keep random values from Math.floor(Math.random() * 10); See to the console.log($scope.logsCreateValue);, it should matches with values from $scope.orders[key].orderNumber = res[key].orderNumber;

Upvotes: 0

Nikos Paraskevopoulos
Nikos Paraskevopoulos

Reputation: 40318

The following is a template for loops with asynchronous bodies, i.e. the next iteration must take place only when an asynchronous task is complete. It works for promises in an Angular context, but can be generalized for any promises implementation I believe:

/**
 * 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);
    }
}

Based on this, here is a crude implementation of your case (watch the browser's console for output).

Upvotes: 2

Related Questions