0

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;
}

I want to 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.

I know that I need to add a callback to part of the code so that it will wait for issueRepository.getIssuesOffline to finish, but because this is part of a $.each() loop I am really struggling to see where this callback would go.

(I have asked this as a new question because the answers given in the suggested duplicate answer are generic examples and don't have a $.each() loop in them).

In the comments below, Bergi has asked for the contents of getissuesOffline:

GetIssuesOffline:

GetIssuesOffline: function (barcode, callback) {
    var me = this;

    issueDatabase.GetIssues(barcode, function (issues) {
        me._processIssues(issues);

        return callback(issues);
    });
}

issueDatabase.getIssues:

GetIssues: function (barcode, callback) {
    var me = this;
    db.transaction(
        function (context) {
            var query = "SELECT * FROM issues WHERE barcode LIKE '" + barcode + "%' ORDER BY offSaleDate DESC LIMIT 25";
            context.executeSql(query, [], function (context, result) {
                var issues = [];

                for (var i = 0; i < result.rows.length; i++) {
                    var issue = result.rows.item(i);
                    issue.Source = dataSources.Local;
                    issue.isRanged = issue.isRanged == 1 ? true : false;
                    issues.push(issue);
                }

                callback(issues);
            }, me.ErrorHandler);
        }
        , me.ErrorHandler);
}

me.processIssues:

_processIssues: function (issues) {
    var me = this;
    $.each(issues, function (index, i) {
        if (i.issueNumber == null) {
            i.issueNumber = '';
        }

        i.issueNumber = i.issueNumber + '';
        i.productNumber = i.productNumber + '';

        if (i.issueNumber.length == 1) {
            i.issueNumber = '0' + i.issueNumber;
        }

        i.barcode = parseInt(i.productNumber + '' + i.issueNumber);
        i.Status = me.GetIssueStatus(i);
        i.supplier = me.GetissueSupplierDetails(i);
        i.ReturnsAmount = ko.observable(0);
        i.Returns = ko.observable({ totes: [] });

            returnsRepository.GetReturn(i.barcode, function (r) {
                i.ReturnsAmount(r.amount);

                if (r.amount > 0) {
                    i.Returns(r);
                } else {
                    i.Returns({ totes: [] });
                }
            });
        };
        i.RefreshReturnsAmount();

        me.IssueDatabase.UpdateIssue(i, function (issue) {
            me.IssueDatabase.UpdateIssueLastUpdated(issue);
        });
    });
}
RussAwesome
  • 464
  • 5
  • 18
  • Maybe you should investigate using promises and async await. – cYrixmorten Nov 07 '17 at 11:45
  • `$.each()` callback ?? – mrid Nov 07 '17 at 11:45
  • "*I want to alter this code so that the calls are no longer asynchronous*" - I don't think it's possible (depends on what `getIssuesOffline` does: show us that code), and I don't think you really want to freeze the browser while running this function. – Bergi Nov 07 '17 at 11:48
  • cYrixmorten I have asked a few questions over the last few days to pare this down to the issue of a null variable not waiting for code to finish, and this is the barest minimum example I have been able to achieve. I do not understand javascript well I'm afraid: I have inherited this project. – RussAwesome Nov 07 '17 at 11:49
  • Bergi, I have added the code as requested. I absolutely do want to freeze the browser at this point, as it is part of an upload routine (and a spinny upload indicator is put on screen first to indicate the processing is taking place before the data is uploaded. I can totally move any parts of the function around, as long as `uploadList` is not returned before the entire `$.each()` loop has been executed. – RussAwesome Nov 07 '17 at 11:54
  • If the browser is frozen then the spinny upload indicator won't spin. – Quentin Nov 07 '17 at 11:56
  • Hi Quentin, thank you. That's OK, I can replace it with a static message. The list it is looping through should only have around 200 items in, so it's not going to take ages to process, but I do need it to finish processing before it returns the `uploadList`. I am currently faking this by adding a setTimeout around the call to this code, which I *know* can't be good practice. – RussAwesome Nov 07 '17 at 12:03

0 Answers0