访问外部范围

时间:2012-11-25 17:03:40

标签: javascript oop

我正在创建一个Users集合,然后能够抓住内部的单个用户。这将用于匹配来自另一个系统,所以我的愿望是加载用户一次,然后能够稍后进行罚款/匹配。但是,我在从内部方法访问外部用户集合时遇到问题。

function Users(){

    var allUsers;

    this.getUsers = function () {
        // ajax to that Jasmine behaves    
        $.ajax({
            url: '../app/data/jira_users.json',
            async: false,
            dataType: 'json',
            success: function(data) {
                allUsers = data;
            }
        });
        return allUsers;
    };

    this.SingleUser = function (name) {
        var rate = 0.0;
        var position;

        this.getRate = function () {
            if(position === undefined){
                console.log('>>info: getting user position to then find rate');
                this.getPosition();
            }

            $.ajax({
                url: '../app/data/rates.json',
                async: false,
                dataType: 'json',
                success: function(data) {
                    rate = data[position];
                }
            });
            return rate;
        };

        this.getPosition = function () {
            console.log(allUsers);
            //position = allUsers[name];
            return position;
        };

        //set name prop for use later I guess.
        this.name = name;
    };
}

以及开始所有这一切的测试:

it("get single user's position", function(){
    var users = new Users();
    var someone = new users.SingleUser('bgrimes');
    var position = someone.getPosition();
    expect(position).not.toBeUndefined();
    expect(position).toEqual('mgr');
});

getPosition方法是个问题(可能很明显)因为allUsers总是未定义的。我在这里有另一种尝试,我尝试了几种方法。我认为问题是如何调用Users.getUsers开始,但我也不确定我是否使用外部和内部变量是正确的。

3 个答案:

答案 0 :(得分:1)

您填写allUsers数据的方法存在缺陷 jquery中的ajax调用是异步的,因此每次调用users.getAllUsers时都不会返回任何内容,稍后调用jquery ajax的成功函数时,allUsers将被填充

答案 1 :(得分:1)

this.getUsers()无效。它返回allUsers独立于获取数据的ajax请求,因为,ajax是异步。与getRate()相同。

您必须使用回调方法,使用回调引用调用getUsers(),当ajax请求完成时,它会将数据传递给回调函数。

类似的东西:

this.getUsers = function (callback) {
    // ajax to that Jasmine behaves    
    $.ajax({
        url: '../app/data/jira_users.json',
        async: false,
        dataType: 'json',
        success: function(data) {
            callback(data);
        }
    });
};

这个电话将是:

var user_data = null;
Users.getUsers(function(data) {
    user_data = data;
});

答案 2 :(得分:1)

虽然其他的都是正确的,因为这不会像你输入的那样有效,但我看到用例是一个茉莉花测试用例。因此,有一种方法可以使您的测试成功。通过执行以下操作,您无需实际运行任何类型的服务器来进行测试。

var dataThatYouWouldExpectFromServer = {
    bgrimes: {
        username: 'bgrimes',
        show: 'chuck',
        position: 'mgr'
    }
};

it("get single user's position", function(){
    var users = new Users();
    spyOn($, 'ajax').andCallFake(function (ajaxOptions) {
        ajaxOptions.success(dataThatYouWouldExpectFromServer);
    });
    users.getUsers();
    var someone = new users.SingleUser('bgrimes');
    var position = someone.getPosition();
    expect(position).not.toBeUndefined();
    expect(position).toEqual('mgr');
});

这将使ajax调用返回您想要它返回的任何内容,这也允许您模拟测试失败,意外数据等。您可以将'dataThatYouWouldExpectFromServer'设置为你想要的任何东西..这可以帮助你想要测试一些不同的结果,但不希望每个结果都有一个JSON文件。

Sorta-edit - 这将修复测试用例,但可能不是代码。我的建议是,每当你依赖ajax调用返回时,请确保你调用的方法有一个'回调'参数。例如:

var users = new Users();
users.getUsers(function () {
    //continue doing stuff
});

您可以嵌套它们,或者您可以(最好)创建回调,然后将它们用作彼此的参数。

var users = new Users(), currentUser;

var showUserRate = function () {
    //show his rate
    //this won't require a callback because we know it's loaded.
    var rate = currentUser.getRate(); 
}

var usersLoaded = function () {
    //going to load up the user 'bgrimes'
    currentUser = new users.SingleUser('bgrimes');
    currentUser.getRate(showUserRate);
}

users.getUsers(usersLoaded);