1

我正在尝试在 JavaScript 中开发一个类,我可以使用它来轻松访问由 AJAX 请求收集的大量数据。唯一的问题是我需要让类的成员只有在 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
})()

目前 getCourse 将在 AJAX 请求完成之前被触发,显然它没有数据可以访问。

任何想法将不胜感激,我坚持这个!

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 请求,您可以调用您的函数,如

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,因为存储对象都在您的自调用函数的闭包中共享。您通常不会将模块模式与原型混合(从模块返回构造函数),除非您真的知道自己在做什么,也就是说,共享闭包变量作为的静态属性工作。

如果我是你,这就是我会做的事情(因为你真的想要私有变量)

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

您可以定义一个函数getData来执行 ajax 请求并将其getCourse作为回调。getData可以在本地存储 Ajax 调用的结果,并在执行 ajax 调用之前测试本地存储。

您还可以指定一个私有成员以允许仅运行一次 ajax 调用。您可能需要检查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 回答