2009-04-16 9 views
3

私はJava、C#などの国から来ています。私が持っているWebアプリケーション用のJavaScriptレポートエンジンで作業しています。私はjQuery、AJAXなどを使用しています。私は自分の気持ちに合わせて作業するのが難しいです。例えば、AJAX呼び出しを行うと、コールバックがオブジェクトのメンバーへのアクセス。これらのコールバック関数は複雑である必要はありませんか?私は間違ったことをする必要があることを知っている。私がより良くできることを指摘してください - 提供されたスニペットがあまりにも/あまりにも/あまりにも/あまりにも恐ろしいかどうかを私に教えてください。私がやろうとしている何このjavascriptをオブジェクト指向のバックグラウンドから読みやすく、維持し、理解しやすくするにはどうすればよいですか?

  • ページのロードでは、私は、ユーザーの選択フルを持っています。
  • 私はレポートを作成して(今は1つ)、それを選択ボックスに追加します。
  • ユーザーとレポートの両方を選択すると、レポートが実行されます。
  • このレポートには、各リーグやトーナメントで一連のコール(練習シリーズ、リーグ、トーナメントを獲得)が含まれています。これらのシリーズはすべて取得され、各シリーズごとにすべてのゲームが取り込まれます。
  • アクティブなコールのカウンタを維持し、すべてのコールが完了すると、レポートが実行されてユーザに表示されます。

コード:

//Initializes the handlers and reports 
function loadUI() { 
    loadReports(); 
    $("#userSelect").change(updateRunButton); 
    $("#runReport").click(runReport); 
    updateRunButton(); 
    return; 
    $("#userSelect").change(loadUserGames); 
    var user = $("#userSelect").val(); 
    if(user) { 
     getUserGames(user); 
    } 
} 

//Creates reports and adds them to the select 
function loadReports() { 
    var reportSelect = $("#reportSelect"); 
    var report = new SpareReport(); 
    engine.reports[report.name] = report; 
    reportSelect.append($("<option/>").text(report.name)); 

    reportSelect.change(updateRunButton); 
} 

//The class that represents the 1 report we can run right now. 
function SpareReport() { 
    this.name = "Spare Percentages"; 
    this.activate = function() { 

    }; 

    this.canRun = function() { 
     return true; 
    }; 

    //Collects the data for the report. Initializes/resets the class variables, 
    //and initiates calls to retrieve all user practices, leagues, and tournaments. 
    this.run = function() { 
     var rC = $("#rC"); 
     var user = engine.currentUser(); 
     rC.html("<img src='/img/loading.gif' alt='Loading...'/> <span id='reportProgress'>Loading games...</span>"); 
     this.pendingOperations = 3; 
     this.games = []; 
     $("#runReport").enabled = false; 
     $.ajaxSetup({"error":(function(report) { 
      return function(event, XMLHttpRequest, ajaxOptions, thrownError) { 
       report.ajaxError(event, XMLHttpRequest, ajaxOptions, thrownError); 
      }; 
     })(this)}); 

     $.getJSON("/api/leagues", {"user":user}, (function(report) { 
      return function(leagues) { 
       report.addSeriesGroup(leagues); 
      }; 
     })(this)); 
     $.getJSON("/api/tournaments", {"user":user}, (function(report) { 
      return function(tournaments) { 
       report.addSeriesGroup(tournaments); 
      }; 
     })(this)); 
     $.getJSON("/api/practices", {"user":user}, (function(report) { 
      return function(practices) { 
       report.addSerieses(practices); 
      }; 
     })(this)); 
    }; 

    // Retrieves the serieses (group of IDs) for a series group, such as a league or 
    // tournament. 
    this.addSeriesGroup = function(seriesGroups) { 
     var report = this; 
     if(seriesGroups) { 
      $.each(seriesGroups, function(index, seriesGroup) { 
       report.pendingOperations += 1; 
       $.getJSON("/api/seriesgroup", {"group":seriesGroup.key}, (function(report) { 
        return function(serieses) { 
         report.addSerieses(serieses); 
        }; 
       })(report)); 
      }); 
     } 
     this.pendingOperations -= 1; 
     this.tryFinishReport(); 
    }; 

    // Retrieves the actual serieses for a series group. Takes a set of 
    // series IDs and retrieves each series. 
    this.addSerieses = function(serieses) { 
     var report = this; 
     if(serieses) { 
      $.each(serieses, function(index, series) { 
       report.pendingOperations += 1; 
       $.getJSON("/api/series", {"series":series.key}, (function(report) { 
        return function(series) { 
         report.addSeries(series); 
        }; 
       })(report)); 
      }); 
     } 
     this.pendingOperations -= 1; 
     this.tryFinishReport(); 
    }; 

    // Adds the games for the series to the list of games 
    this.addSeries = function(series) { 
     var report = this; 
     if(series && series.games) { 
      $.each(series.games, function(index, game) { 
       report.games.push(game); 
      }); 
     } 
     this.pendingOperations -= 1; 
     this.tryFinishReport(); 
    }; 

    // Checks to see if all pending requests have completed - if so, runs the 
    // report. 
    this.tryFinishReport = function() { 
     if(this.pendingOperations > 0) { 
      return; 
     } 
     var progress = $("#reportProgress"); 
     progress.text("Performing calculations..."); 
     setTimeout((function(report) { 
      return function() { 
       report.finishReport(); 
      }; 
     })(this), 1); 
    } 

    // Performs report calculations and displays them to the user. 
    this.finishReport = function() { 
     var rC = $("#rC"); 

     //snip a page of calculations/table generation 
     rC.html(html); 

     $("#rC table").addClass("tablesorter").attr("cellspacing", "1").tablesorter({"sortList":[[3,1]]}); 
    }; 

    // Handles errors (by ignoring them) 
    this.ajaxError = function(event, XMLHttpRequest, ajaxOptions, thrownError) { 
     this.pendingOperations -= 1; 
    }; 

    return true; 
} 

// A class to track the state of the various controls. The "series set" stuff 
// is for future functionality. 
function ReportingEngine() { 
    this.seriesSet = []; 
    this.reports = {}; 
    this.getSeriesSet = function() { 
     return this.seriesSet; 
    }; 
    this.clearSeriesSet = function() { 
     this.seriesSet = []; 
    }; 
    this.addGame = function(series) { 
     this.seriesSet.push(series); 
    }; 
    this.currentUser = function() { 
     return $("#userSelect").val(); 
    }; 
    this.currentReport = function() { 
     reportName = $("#reportSelect").val(); 
     if(reportName) { 
      return this.reports[reportName]; 
     } 
     return null; 
    }; 
} 

// Sets the enablement of the run button based on the selections to the inputs 
function updateRunButton() { 
    var report = engine.currentReport(); 
    var user = engine.currentUser(); 
    setRunButtonEnablement(report != null && user != null); 
} 

function setRunButtonEnablement(enabled) { 
    if(enabled) { 
     $("#runReport").removeAttr("disabled"); 
    } else { 
     $("#runReport").attr("disabled", "disabled"); 
    } 

} 

var engine = new ReportingEngine(); 

$(document).ready(function() { 
    loadUI(); 
}); 

function runReport() { 
    var report = engine.currentReport(); 
    if(report == null) { 
     updateRunButton(); 
     return; 
    } 
    report.run(); 
} 

私は、ユーザーのゲームのサブセットのみで動作しますそのうちのいくつかの新しいレポートを追加を開始しようとしています。私はサブクラス(プロトタイプ?)を使用しようとしていますが、もしこれを単純化する方法がわからなければ...その文をどのように終了するのか分かりません。助けて!

答えて

3
$.getJSON("/api/leagues", {"user":user}, (function(report) { 
     return function(leagues) { 
      report.addSeriesGroup(leagues); 
     }; 
    })(this)); 

は、のように書くことができます:あなたはループの中にいると、ループの周りたびに変化変数にバインドするとき

var self = this; 
$.getJSON("/api/leagues", {"user":user}, (function(leagues) { 
      self.addSeriesGroup(leagues); 
     }); 

機能を返す関数は、より有用です。

+0

ありがとうございます。私は簡単な方法がなければならないことを知っていた! –

2

必要に応じて「いくつかの」コメントを記入してください。

+0

いくつかのコメントを追加しました。申し訳ありません。 –

1

私はあなたに正直で、すべてを読まなかったと言います。しかし、私はあなたが知っておくべきJavaScriptについて何かがあると思います。それはクロージャがあるということです。

var x = 1; 
$.ajax({ 
    success: function() { 
    alert(x); 
    } 
}); 

どんなにそれが完了するために、AJAX要求のために要する時間の時間、それはxへのアクセスを持っていないし、それが成功したら、「1」を警告します。

+1

彼は実際にすでにクロージャを使用していますが、必要以上に複雑な方法で行っています – Greg

1

クロージャを理解してください。これには慣れています。 (多くの人が使用していますが、確かに物事についての典型的な方法ですので、それがどうなっているのか分かりましたら分かります)

This is a good thread効果的な使い方を簡単に説明します。

あなたがメソッドを定義し、継承を行うために prototypesを使用する必要があります
1

function Parent(x) { 
    this.x = x; /* Set an instance variable. Methods come later. */ 
} 

/* Make Parent inherit from Object by assigning an 
* instance of Object to Parent.prototype. This is 
* very different from how you do inheritance in 
* Java or C# ! 
*/ 
Parent.prototype = { /* Define a method in the parent class. */ 
    foo: function() { 
    return 'parent ' + this.x; /* Use an instance variable. */ 
    } 
} 

function Child(x) { 
    Parent.call(this, x) /* Call the parent implementation. */ 
} 

/* Similar to how Parent inherits from Object; you 
* assign an instance of the parent class (Parent) to 
* the prototype attribute of the child constructor 
* (Child). 
*/ 
Child.prototype = new Parent(); 

/* Specialize the parent implementation. */ 
Child.prototype.foo = function() { 
    return Parent.prototype.foo.call(this) + ' child ' + this.x; 
} 

/* Define a method in Child that does not override 
* something in Parent. 
*/ 
Child.prototype.bar = function() { 
    return 'bar'; 
} 

var p = new Parent(1); 
alert(p.foo()); 

var ch = new Child(2); 
alert(ch.foo()); 
alert(ch.bar()); 

私はjQueryを使って慣れていないんだけど、私はPrototype library(史上最悪名の選択を)知っているが、作業しやすいよう、いくつかの機能があります継承あり。

また、この質問の答えが出てくる間に、私は参考になるかもしれないhow to do OO right in JSの詳細にある素敵なページを見つけました。

関連する問題