-1

I call the following function:

function uploadReturns() {
    var uploads = me.getIssuesFromReturnsList();
    uploadreturnsobjects(uploads); //process the uploads object and send it to an AJAX call

}

In me.getIssuesFromReturnsList the uploadList variable is being returned before the rest of the code executes because it is asynchronous (as per this question)

me.getIssuesFromReturnsList = function () {
    var uploadList = [];
    $.each(me.returnsList(), function (index, i) {
        var issue = issueRepository.GetDefaultIssue();
        issue.barcode = i.barcode;
        issue.ReturnsAmount(i.amount);

        var uploadItem = {
            barcode: i.barcode,
            amount: i.amount,
            issue: ko.observable(issue)
        };

        uploadList.push(uploadItem);

        issueRepository.GetIssuesOffline(i.barcode, function (issues) {
            if (issues.length > 0) {
                uploadItem.issue(issues[0]);
            }
        });
    });

    return uploadList;
}

How can I alter this code so that the calls are no longer asynchronous, and instead waits for all the inner code to execute before returning the uploadList?

RussAwesome
  • 464
  • 5
  • 18
  • Wrap it in a `Promise`? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise – sjahan Nov 07 '17 at 09:58

1 Answers1

-1

using Promises:

function forEachChain (array, func, thisArg) {
    const res = [];

    function exec(resolve, i) {
        func.call(thisArg, array[i]).then((e) => {
            res[i] = e;
            if (i < array.length - 1) {
                exec(resolve, i + 1);
            } else {
                resolve(res);
            }
        }, (err) => {
            res[i] = err;
            if (i < array.length - 1) {
                exec(resolve, i + 1);
            } else {
                resolve(res);
            }
        });
    }

    return new Promise((resolve) => {
        if (array.length > 0) {
            exec(resolve, 0);
        } else {
            resolve([]);
        }
    });
}

now you can call this function passing an array. for each element of that array func is called (passed by you) assuming that it returns a Promise too.

The asynchronous calls are called one per time (the concurrent version is a bit more complicated).

In case of Errors, the array will contain the relative error at the relative index.

forEachChain(myArray, myFuncReturningAPromise, thisArgInsideEachFuncCall).then((arrOfSameSizeOfMyArray) => { 
    // myCallback
}
FrontTheMachine
  • 526
  • 3
  • 14