1

AJAXリクエストによって収集された大量のデータに簡単にアクセスするために使用できるクラスをJavaScriptで開発しようとしています。唯一の問題は、AJAX 呼び出しが完了した後でのみ、クラスのメンバーにアクセスできるようにする必要があることです。理想的には、スクリプトでこれを呼び出すことができるものになりたいと思っています。

courses.getCourse('xyz').complete = function () {
    // do something with the code
}

これは、AJAX 呼び出しが完了し、「クラス」内のデータ構造を使用する準備が整った後にのみ発生します。理想的には、クラス内のすべての関数に対して .complete メンバーを作成する必要はありません

これまでに作成しようとしている「クラス」は次のとおりです。

var model_courses = (function() {

    var cls = function () {

        var _storage = {}; // Used for storing course related info
        _storage.courses = {}; // Used for accessing courses directly
        _storage.references = new Array(); // Stores all available course IDs

        var _ready = 0;
        $.ajax({
            type: "GET",
            url: "data/courses.xml",
            dataType: "xml",
            success: function(xml) {
                $(xml).find("course").each(function() {

                    _storage.courses[$(this).attr('id')] = {
                        title       : $(this).find('title').text(),
                        description : $(this).find('description').text(),
                        points      : $(this).find('points').text()
                    }
                    _storage.references.push($(this).attr('id'))

                })

            }
        })

        console.log(_storage.courses)

    }
    cls.prototype = {
            getCourse: function (courseID) {
                console.log(cls._storage)
            },
            getCourses: function () {
                return _storage.courses
            },
            getReferences: function (),
                return _storage.references
            }

    }
    return cls
})()

現時点では、AJAX リクエストが完了する前に getCourse が起動され、明らかにアクセスするデータがありません。

どんなアイデアでも大歓迎です、私はこれにこだわっています!

4

4 に答える 4

3

jQueryは、あなたが探しているものを誤解していない限り、遅延オブジェクトを使用してこれをすでに処理しています。

var courses = {
    getCourse: function (id) {
        return $.ajax({url:"getCourse.php",data:{id:id});
    }
};

courses.getCourse("history").done(function(data){
    console.log(data);
});

私はこれがあなたが探しているものではないことを知っています、私はそれがあなたを正しい方向に押し進めるのに十分であることを望んでいます。延期されたオブジェクトは素晴らしいです。

于 2012-04-25T18:17:31.787 に答える
1

次の変更により、AJAXリクエストを1回だけ行うことができ、次のように関数を呼び出すことができます。

courses.getCourse('xyz', function(course){
    // Use course here
});

これが変更点です

var model_courses = (function() {

    // This is what gets returned by the $.ajax call
    var xhr;
    var _storage = {}; // Used for storing course related info
    _storage.courses = {}; // Used for accessing courses directly
    _storage.references = []; // Stores all available course IDs

    var cls = function () {
        xhr = $.ajax({
            type: "GET",
            url: "data/courses.xml",
            dataType: "xml",
            success: function(xml) {
                $(xml).find("course").each(function() {

                    _storage.courses[$(this).attr('id')] = {
                        title       : $(this).find('title').text(),
                        description : $(this).find('description').text(),
                        points      : $(this).find('points').text()
                    }
                    _storage.references.push($(this).attr('id'))

                });
            }
        });
    }
    cls.prototype = {
            // Made changes here, you'd have to make the same 
            // changes to getCourses and getReferences
            getCourse: function (courseID, callback) {
                if (xhr.readyState == 4) {
                     callback(_storage.courses[courseID]);
                }
                else {
                   xhr.done(function(){
                      callback(_storage.courses[courseID]);
                   })
                }

            },
            getCourses: function () {
                return _storage.courses
            },
            getReferences: function (),
                return _storage.references
            }

    }
    return cls
})()

model_coursesちなみに、これらのオブジェクトの2つをインスタンス化する必要がある場合、ストレージオブジェクトはすべて自己呼び出し関数のクロージャで共有されるため、モジュールパターンはうまく機能しません。何をしているのかを本当に理解していない限り、通常、モジュールパターンとプロトタイプ(モジュールからコンストラクターを返す)を混在させることはありません。つまり、共有クロージャー変数はクラスの静的プロパティとして機能します。

これは私があなただったら私がすることです(あなたは本当にプライベート変数が欲しいので)

function ModelCourses() {
    var storage = {
      courses: {},
      references: []
    };

    var xhr = $.ajax({
        type: "GET",
        url: "data/courses.xml",
        dataType: "xml",
        success: function(xml) {
            $(xml).find("course").each(function() {   
                storage.courses[$(this).attr('id')] = {
                    title       : $(this).find('title').text(),
                    description : $(this).find('description').text(),
                    points      : $(this).find('points').text()
                }
                storage.references.push($(this).attr('id'))
            })    
        }
    });

    this.getCourse = function(courseId, callback) {
        function getCourse() {
            callback(storage.courses[courseID])
        }
        if (xhr.readyState == 4) {
            getCourse();
        }
        else {
            xhr.done(getCourse);
        }
    };   
}
于 2012-04-25T19:16:16.147 に答える
0

盗むデータがあるかどうかを確認するチェックを追加するgetStorageか(推奨)、アクセスできるアイテムがある場合に公開するよりも「実際の」メソッドを非公開にします。(最初の方法をお勧めしますが、そうしないと、オブジェクトに存在しないメソッドの呼び出しに関して例外が発生します)。

于 2012-04-25T18:17:34.577 に答える
0

ajax リクエストを実行し、 をコールバックとしてgetData受け取る関数を定義できます。getCourseおそらく、Ajax 呼び出しのgetData結果をローカルに保存し、ajax 呼び出しを実行する前にローカル ストレージをテストできます。

プライベート メンバーを指定して、ajax 呼び出しを 1 回だけ実行できるようにすることもできます。便利なツールについては、underscore.jsを確認してください。

短いコード例を次に示します。

cls.prototype.getData = function(callback) {
    /*perform ajax call or retrieve data from cache*/
    callback()
}
cls.prototype.getCourse = function(id) {
    this.getData(function() {
        /*do something with the data and the id you passed*/
    }
}
于 2012-04-25T18:41:55.663 に答える