Domanda

I have a mobile app for which I am using Azure Mobile Services as a backend. I have a scenario in which I need to modify the elements that the client is requesting from the database. I need to compute the rank and percentile of the record being requested, based on its best score and the best scores of all other records in the table. I followed the example here and wrote the below script:

function read(query, user, request) {
    request.execute({
        success: function(results) {
            results.forEach(function(item) {
                var totalsql = "SELECT COUNT(*) FROM scoreInfo";
                mssql.query(totalsql, {
                    success: function(totalresults) {
                        var totalCount = totalresults[0].Column0;

                        var moresql = "SELECT COUNT(*) FROM scoreInfo WHERE bestscore > ?";      
                        mssql.query(moresql, [item.bestscore], {
                            success: function(moreresults) {
                                var moreBestCount = moreresults[0].Column0;

                                item.bestrank = moreBestCount + 1;
                                item.bestpercentile = 100 - moreBestCount*100/(totalCount+1);                                
                            }
                        });
                    }
                });
            });
            request.respond();
        }
    });
}

But I don't see the results as expected on the client side. I even tried logging the results on the server side but what I see on the client side doesn't match what is logged. What am I doing wrong?

È stato utile?

Soluzione

The problem here is that the mssql.query function is asynchronous. What ends up happening is that in the forEach loop you're firing many asynchronous mssql requests, and right after that (without waiting for them to complete) you're callng request.respond(); At that time you still don't have any of the responses (remember that node.js is single-threaded, so none of the responses have arrived yet).

What you'll need to do is to delay calling request.respond() until all the responses to the mssql calls have arrived. The code below shows one way of doing that.

function read(query, user, request) {
    request.execute({
        success: function(results) {
            var updateResult = function(index) {
                if (index >= results.length) {
                    // all done
                    request.respond();
                } else {
                    var item = results[index];
                    var totalsql = "SELECT COUNT(*) FROM scoreInfo";
                    mssql.query(totalsql, {
                        success: function(totalresults) {
                            var totalCount = totalresults[0].Column0;

                            var moresql = "SELECT COUNT(*) FROM scoreInfo WHERE bestscore > ?";
                            mssql.query(moresql, [item.bestscore], {
                                success: function(moreresults) {
                                    var moreBestCount = moreresults[0].Column0;

                                    item.bestrank = moreBestCount + 1;
                                    item.bestpercentile = 100 - moreBestCount*100/(totalCount+1);

                                    updateResult(index + 1); // update next result
                                }
                            });
                        }
                    });
                }
            }

            updateResult(0);
        }
    });
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top