Question

I am getting data back from my azure mobile service db.In the read script I am trying to modify the response as shown here http://msdn.microsoft.com/en-us/library/jj631631.aspx. I am using the tracking number found in the results to use a node module called "ups_node".I am adding a status property to my results to pass pack to the client. This all works until I loop through the results. It is not waiting untill the confirmTracking.makeRequest method is complete before it continues the loop. Therefore if there is one record in the loop it is complete before the tracking request comes back. I am not sure how to sync everything up.

function read(query, user, request) {
    request.execute({
        success: function (results) {
            results.forEach(function (item) {
                var tn = item.trackingnumber;
                //below request being made for shipping status given the tracking number                   
                confirmTracking.makeRequest({
                    customerContext: "Customer Data",
                    trackingNumber: tn
                }, function (data, err) {
                    if (err) {
                        console.error(e);
                        request.respond(500, err);
                    }
                    if (data) {
                        var db = SpahQL.db(data);
                        var all_desc = db.select(
                            "/TrackResponse/Shipment/0/Package/0/Activity/0/Status/0/StatusType/0/Description"
                        );
                        var resp = {};
                        try {
                            var strParse = JSON.stringify(all_desc.value());
                            resp = JSON.parse(strParse);
                        } catch (e) {
                            // An error has occured, handle it, by e.g. logging it
                            console.log(e);
                            request.respond(500, e);
                        }
                        var status = JSON.stringify(resp);
                        item.Status = resp[0];
                        console.log('item.Status =  ' + item.Status); // this is being called after the one out side the confirmTracking.makeRequest method.
                    }
                })
                //above request is being made for shipping status given the tracking number 
                console.log('item.Status =  ' + item.Status); //this is happening before it is being set in the above confirmTracking.makeRequest method therefore it is undefined
            });
            request.respond(); //Writes the response
        }
    });
}
Was it helpful?

Solution

You have to be careful with how you're handling request.respond when making asynchronous calls with Node.js because you can inadvertently respond before you mean to. If I understand what you're trying to do above, you're executing the request and then you want to loop through each of the results and call confirmTracking.makeRequest on it. So essentially a separate process will be created each time you call makeRequest. As soon as the last record is hit by the forEach call, the request.respond() you have at the bottom will be called. This means that your READ script will respond to the calling application before the calls to makeRequest are done.

What you need to do is a tad complicated but start by removing the calls to request.respond(). You only want to call this once when things are done. In order to know that things are done, you'll need to keep track of how many requests have been made. So you'll want to do something like this:

success: function (results) {
    var recordCount = results.length;
    var recordsProcessed = 0;
    results.forEach(function(item) {
        confirmTracking.makeRequest({...}
        , function(data, err) {
            recordsProcessed++;
            //DoProcessingHere
            //Only call request.respond if recordsProcessed == recordCount
        })
    })
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top