0

私は次のコードを持っています:

    displayOrders: function(){
    function getRetailerName(retailerID, callback){
        var retailerName;
        db.transaction(function(qry){
            qry.executeSql("SELECT retailerName FROM retailers WHERE token = '"+retailerID+"' ", [], function(tx, results1){
                var len1 = results1.rows.length;
                var retailerName;
                for (var i1=0; i1<len1; i1++){
                    retailerName = results1.rows.item(i1).retailerName;
                    callback(retailerName);
                }
            });
        });
    }
    db.transaction(function(qry){
        qry.executeSql("SELECT * FROM orders", [], function(tx, results){
            //query was a success
            var len = results.rows.length;
            for (var i=0; i<len; i++){
                var orderTime = results.rows.item(i).orderTime;

                var retailerName;
                getRetailerName(results.rows.item(i).retailerID,function(name) { //this uses a callback function... need to because request to DB is a
                    retailerName = name ;
                    $('#orderHistoryCollapsible').append('<div data-role="collapsible" data-collapsed="false"><h3>'+retailerName+' - '+orderTime+'</h3><p>Im the collapsible set content for section 1.</p></div>');
                    $(".orderHistoryCollapsible").collapsibleset();
                    $(".orderHistoryCollapsible").collapsibleset('refresh');            
                });
            }
        });

    });     

したがって、基本的に、コードは2つの別々のデータベースクエリを実行し、リストビューに配置されるデータを取得します。getRetailerName関数は、以下のクエリで使用されるコールバックを提供します。このコールバックは、両方のデータセットを「orderHistoryCollapsible」divに追加します。

私の問題は、DOMに挿入されることも意図されているorderTime値が、毎回ループの最後の値を返すことです。まるで両方のクエリをコールバックとして提供する必要があるかのように?しかし、データを適切な場所に追加する方法がわかりません。

どんな助けでもいただければ幸いです

4

2 に答える 2

1

変数orderTimeは関数スコープ(function(tx, results))にあり、ループスコープにはありません。つまり、のクロージャでキャプチャされた場合、function(name)インスタンスは1つだけです。そして、ループが終了すると、最後の呼び出しの値になります。

ループ本体を無名関数で囲むと、これを修正できます

for (var i=0; i<len; i++){
    function() {
        var orderTime = results.rows.item(i).orderTime;

        var retailerName;
        getRetailerName(results.rows.item(i).retailerID,function(name) { //this uses a callback function... need to because request to DB is a
            retailerName = name ;
            $('#orderHistoryCollapsible').append('<div data-role="collapsible" data-collapsed="false"><h3>'+retailerName+' - '+orderTime+'</h3><p>Im the collapsible set content for section 1.</p></div>');
            $(".orderHistoryCollapsible").collapsibleset();
            $(".orderHistoryCollapsible").collapsibleset('refresh');            
        });
    }
}

次に、本体が実行されるたびに新しいスコープがあり、したがっての新しいインスタンスがありorderTimeます。

于 2013-02-27T12:39:30.880 に答える
1

var orderTimejavascriptでは、ローカル変数のスコープは(Javaのように)囲んでいるブロックではなく、囲んでいる関数に制限されているため、コードでは誤解を招く可能性があります。より具体的には、あなたorderTimeは一度初期化され、ループの反復ごとに上書きされます(つまり、毎回同じ変数です)。

コールバック関数はその変数を参照します(これはクロージャと呼ばれます。つまり、コールバック関数には変数への参照があるため、変数が定義された関数が終了した後に変数が存在します)。コールバックが呼び出されるまでに、ループは実行を終了しているため、orderTimeは最後の値になります。

以下が機能するはずです。

displayOrders: function(){
    function getRetailerName(retailerID, callback){
        var retailerName;
        db.transaction(function(qry){
            qry.executeSql("SELECT retailerName FROM retailers WHERE token = '"+retailerID+"' ", [], function(tx, results1){
                var len1 = results1.rows.length;
                var retailerName;
                for (var i1=0; i1<len1; i1++){
                    retailerName = results1.rows.item(i1).retailerName;
                    callback(retailerName);
                }
            });
        });
    }

    function callbackFn(orderTime) {
        return function(name) {
                $('#orderHistoryCollapsible').append('<div data-role="collapsible" data-collapsed="false"><h3>'+name+' - '+orderTime+'</h3><p>Im the collapsible set content for section 1.</p></div>');
                $(".orderHistoryCollapsible").collapsibleset();
                $(".orderHistoryCollapsible").collapsibleset('refresh');    
        };
    }

    db.transaction(function(qry){
        qry.executeSql("SELECT * FROM orders", [], function(tx, results){
            //query was a success
            var len = results.rows.length;
            for (var i=0; i<len; i++){
                var orderTime = results.rows.item(i).orderTime;
                getRetailerName(results.rows.item(i).retailerID, callbackFn(orderTime));
            }
        });

    });     
于 2013-02-27T12:44:51.257 に答える