0

I'm utilizing an async approach to an iteration in order to call several AJAX requests for each object inside an array called rsPatients (i.e., I use an if conditional instead of a for loop), and inside this iteration is a chained Promise.

function BuildBoardTable() {
    var objLength = Object.keys(rsPatients).length
    if (objLength === 0) {
        $('#tblMessageData').html('<tr style="vertical-align:top;"><td style="background-color:#EEE;" colspan="8">No Patients</td></tr>');
        return false;
    }
    var phoneNumber;
    var rsDevice;
    var counter = 0;

    getExternalData();

    function getExternalData() {
        if (counter < objLength) {
            var CaseNumber = rsPatients[counter].CaseNo;
            var Loc_Code = rsPatients[counter].LocationCode;

            getPhoneNumber(CaseNumber, Loc_Code).then(function () {
                console.log(counter);
                console.log('get1');                 //[breakpoint #1]
            }).then(function () {
                getDeviceData(CaseNumber, Loc_Code); //[breakpoint #2]
            }).then(function () {
                console.log('get2');                 //[breakpoint #4]
            }).then(function () {
                console.log('get3');                 //[breakpoint #5]
                counter++;
            }).finally(function () {
                getExternalData();                   //[breakpoint #6]
            });
        } else {
            counter = 0;
            $('#content-holder > .appwait').hide();
        }
    }

    function getPhoneNumber(CaseNumber, Loc_Code) {
        return new Promise(function (resolve, reject) {
            $.ajax({
                type: 'GET',
                url: 'api/Phone/PatientNumber',
                data: {
                    'case_no': CaseNumber,
                    'loc_code': Loc_Code
                },
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function (result) {
                    phoneNumber = result.Number;
                    console.log(result.Number);
                    resolve(result);
                },
                failure: function (xhr, status, error) {
                    console.log(xhr + ", " + status + ": " + error);
                    alert(xhr + ", " + status + ": " + error);
                    phoneNumber = '';
                    reject(error);
                }
            });
        });
    }

    function getDeviceData(CaseNumber, Loc_Code) {
        $.ajax({
            type: 'GET',
            url: 'api/Phone/PatientDevice',
            data: {
                'case_no': CaseNumber,
                'loc_code': Loc_Code
            },
            contentType: 'application/json; charset=utf-8',
            dataType: 'json',
            success: function (result) {
                rsDevice = result;
                console.log(result);                   //[breakpoint #3]
            },
            failure: function (xhr, status, error) {
                console.log(xhr + ", " + status + ": " + error);
                alert(xhr + ", " + status + ": " + error);
                rsDevice = null;
            }
        });
    }
}

What I expect the console to read like (replacing actual phone numbers & device data with placeholders, of course):

555-555-5555
0
get1
{ApplicationCode: '', LDID: 0, LoanerID: ''}   
get2
get3
555-555-5555
0
get1
{ApplicationCode: '', LDID: 0, LoanerID: ''}   
get2
get3
555-555-5555
0
get1
{ApplicationCode: '', LDID: 0, LoanerID: ''}   
get2
get3
. . .

What I actually see:

555-555-5555
0
get1
get2
get3
555-555-5555
1
get1
get2
get3
{ApplicationCode: '', LDID: 0, LoanerID: ''}
555-555-5555
2
get2
get3
{ApplicationCode: '', LDID: 0, LoanerID: ''}
{ApplicationCode: '', LDID: 0, LoanerID: ''}
555-555-5555
3
get1
get2
{ApplicationCode: '', LDID: 0, LoanerID: ''}
. . . 

When running the application in Debug Mode in Visual Studio, it hits the breakpoints in the following order: 1, 2, 4, 5, 6, 3. If I move breakpoint #3 to the line above, rsDevice = result;, it's the same order.

Why is getDeviceData finishing last in the Promise chain? Or, at the very least, finishing at its own pace from the rest? This will affect which device data is applied to which patient/case number, and obviously we don't want a mismatch to occur here.

  • You're not waiting for `getDeviceData()`. Neither does `getDeviceData` return a promise, like `getPhoneNumber` does, nor does your `.then()` callback `return` the promise to make the chain wait for it – Bergi Jul 28 '22 at 17:04
  • "*Why is [it not] finishing at its own pace from the rest?*" - actually it is. – Bergi Jul 28 '22 at 17:06
  • "*This will affect which device data is applied to which patient/case number*" - don't use global variables for these things. Instead, resolve your promises with the data, and then [properly access these results](https://stackoverflow.com/q/28250680/1048572) – Bergi Jul 28 '22 at 17:07
  • @Bergi, That did it. Thank you. Posting the answer now.... – T_O_Massey Jul 28 '22 at 17:27

1 Answers1

0

@Bergi pointed out that I'm not waiting for, nor returning, a promise for getDeviceData, which I didn't realize I had to do. Here is my revision, which fixed the issue:

    function getExternalData() {
        
            . . . 

            getPhoneNumber(CaseNumber, Loc_Code).then(function (data) {
                console.log(counter);
                console.log('get1');
            }).then(function () {
                return getDeviceData(CaseNumber, Loc_Code);  
                // ^ needed to actually *return* the function
            }).then(function (data) {                        
                // ^ needed to pass the Promise's resolve into the next function
                console.log('get2');
            }).then(function () {
                console.log('get3');
                counter++;
            }).finally(function () {
                getExternalData();
            });
        } else {
            counter = 0;
            $('#content-holder > .appwait').hide();
        }
    }

    . . . 

    function getDeviceData(CaseNumber, Loc_Code) {
        return new Promise(function (resolve, reject) {  //<== added 
            $.ajax({
                type: 'GET',
                url: 'api/Phone/PatientDevice',
                data: {
                    'case_no': CaseNumber,
                    'loc_code': Loc_Code
                },
                contentType: 'application/json; charset=utf-8',
                dataType: 'json',
                success: function (result) {
                    rsDevice = result;
                    console.log(result);
                    resolve(result);    //<== added
                },
                failure: function (xhr, status, error) {
                    console.log(xhr + ", " + status + ": " + error);
                    alert(xhr + ", " + status + ": " + error);
                    phoneNumber = '';
                    reject(error);    //<== added
                }
            });
        });    //<== added
    }