0

バックエンドとして Azure Mobile Services を使用しているモバイル アプリがあります。クライアントがデータベースから要求している要素を変更する必要があるシナリオがあります。要求されているレコードのランクとパーセンタイルを、その最高スコアとテーブル内の他のすべてのレコードの最高スコアに基づいて計算する必要があります。ここの例に従って、以下のスクリプトを作成しました。

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

しかし、クライアント側で期待どおりの結果が得られません。サーバー側で結果をログに記録しようとしましたが、クライアント側で表示される内容はログに記録された内容と一致しません。私は何を間違っていますか?

4

1 に答える 1

2

ここでの問題は、mssql.query関数が非同期であることです。最終的に何が起こるかというと、forEachループ内で多くの非同期 mssql 要求を発行し、その直後に (それらが完了するのを待たずに) 呼び出しているということです。request.respond();その時点では、まだ応答がありません ( node.js はシングル スレッドであるため、応答はまだ到着していません)。

必要なことはrequest.respond()、mssql 呼び出しに対するすべての応答が到着するまで、呼び出しを遅らせることです。以下のコードは、その方法の 1 つを示しています。

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);
        }
    });
}
于 2013-01-26T23:33:55.383 に答える