Eyad
Eyad

Reputation: 14229

Azure mobile service - reading from two tables and return custom response object

I am writing Azure Mobile Service (AMS) API with JavaScript backend named customertickets and in the .get function I am attempting to read values from two tables in my AMS.

The two tables are 'User' and 'Ticket' and I am attempting to retrieve all tickets based on the passed parameter (phonenumber) and return some statistical data. Additionally, I am injecting a custom return value item.spname when looping through the tickets if the ticket satisfy a certain condition (item.parsedjsondata.SPId is not null or empty).

Here is the complete code (ctrl+F 'THIS DOES NOT WORK!'):

//Get ticket info by customer phonenumber
exports.get = function(request, response) {
    var phonenumber = request.query.phonenumber;
    var activeTicketsCounter = 0;
    var completedTicketsCounter = 0;
    var canceledTicketCounter = 0;
    var needCustomerRatingTicketCounter = 0;
    var includeCounterData = request.query.includeCounterData;


    console.log("customertickets/get phonenumber: " + phonenumber);

    request.service.tables.getTable('Ticket').read({
        //SEE: http://stackoverflow.com/questions/24406110/how-to-get-system-properties-createdat-version-in-javascript-backend-of-azu
        systemProperties: ['__createdAt', '__updatedAt'],
        success: function(result) {

            //No ticket is found
            if (result.length === 0) {
                console.log("customertickets/get: no ticket found");
                response.send(statusCodes.NOT_FOUND, { message: "customertickets/get: no ticket is found" });

            }
            //return tickets after filtration based on the customer phonenumber
            else {
                console.log("customertickets/get: ticket found");
                var filteredResults = [];
                result.forEach(function(item) {
                    //only tickets with matched phonen number
                    if (JSON.parse(item.jsondata).customerPhonenumber == phonenumber) {
                        console.log(item);

                        //Adding parsed jsondata to item
                        item.parsedjsondata = JSON.parse(item.jsondata);

                        //Adding the name of the assigned spid; only if spid is not null ie. ticket is already assinged
                        if (item.parsedjsondata.SPId) {

                            console.log("SPID", item.parsedjsondata.SPId);
                            console.log("customerId", item.parsedjsondata.customerId);

                            //This works as expected
                            item.spid = item.parsedjsondata.SPId;

                            request.service.tables.getTable('User').where({ id: item.parsedjsondata.SPId.toString(), usertype: "200" }).read({

                                success: function(userResults) {
                                    console.log('result', userResults[0]);
                                    //Does not exist; return NOT FOUND as sp name!
                                    if (userResults.length === 0) {
                                        //This wroks fine and logs the expected result
                                        console.log("customertickets/get: not SPname found", item.parsedjsondata.SPId);
                                        //THIS DOES NOT WORK!
                                        item.spname = "Service Provider Name Not Found";
                                    }
                                    //Record exists; return it
                                    else {
                                        //This wroks fine and logs the expected result
                                        console.log("retrieved spname", JSON.parse(userResults[0].userjsondata).businessData.businessname.ar);
                                        //THIS DOES NOT WORK!
                                        item.spname = JSON.parse(userResults[0].userjsondata).businessData.businessname.ar;
                                    }

                                }
                            });


                        }


                        //ActiveTicketsCounter
                        if (item.parsedjsondata.ticketStatus == "TicketStatus_ToBeAssigned"
                            || item.parsedjsondata.ticketStatus == "TicketStatus_IsAssigned"
                            || item.parsedjsondata.ticketStatus == "TicketStatus_InProgress"
                            || item.parsedjsondata.ticketStatus == "TicketStatus_SPDisputed_CustomerNotReachable"
                            || item.parsedjsondata.ticketStatus == "TicketStatus_SPDisputed_OutOfScope"
                            || item.parsedjsondata.ticketStatus == "TicketStatus_SPDisputed_CustomerCanceled"
                            || item.parsedjsondata.ticketStatus == "TicketStatus_SPDisputed_PriceDisagreement") {
                            activeTicketsCounter++;
                        }

                        //needCustomerRatingTicketCounter
                        if (item.parsedjsondata.ticketStatus == "TicketStatus_Completed_No_Customer_Rating") {
                            needCustomerRatingTicketCounter++;
                        }

                        //CompletedTicketsCounter
                        if (item.parsedjsondata.ticketStatus == "TicketStatus_Completed_And_Customer_Rated") {
                            completedTicketsCounter++;
                        }

                        //canceledTicketCounter
                        if (item.parsedjsondata.ticketStatus == "TicketStatus_CanceledByB8akAgent") {
                            canceledTicketCounter++;
                        }

                        //Testing: it works!
                        item.testing = "Testing Something!";

                        console.log("item.spname before push:", item.spname);
                        //pushing the found item to the list of results
                        filteredResults.push(item);
                    }
                });

                console.log("includeCounterData: " + includeCounterData);

                if (includeCounterData == true) {
                    //After the loop, add the counters to the filteredresults to be returned
                    filteredResults.push({
                        activeTickets: activeTicketsCounter,
                        pendingCustomerRatingTickets: needCustomerRatingTicketCounter,
                        completedTickets: completedTicketsCounter,
                        canceledTickets: canceledTicketCounter
                    });
                }



                response.send(statusCodes.OK, filteredResults);
            }

        }
    });
};

My main issue is that item.spname is never assigned a value and does not get returned in the response. I can see that the assigned value of item.spname which is JSON.parse(userResults[0].userjsondata).businessData.businessname.ar logs successfully in the AMS log but it does not get returned in the response.

Upvotes: 0

Views: 305

Answers (1)

carlosfigueira
carlosfigueira

Reputation: 87228

The problem you have is that you're not waiting for the result of the many calls to

request.service.tables.getTable('User').where(...).read(...

to arrive before sending the response back to the client. Remember that almost everything in the node.js / JavaScript backend is asynchronous. When you call read on the User table, it won't wait for the result to arrive before executing the next statement - instead, it will queue the operation so that when the response is available, it will be executed.

To fix this you'll need to make all read calls to the users table, and only after you've got all the callbacks is when you can call response.send.

Upvotes: 1

Related Questions