Значение this в функции обратного вызова - PullRequest
4 голосов
/ 08 мая 2009

У меня есть этот код для выполнения ajax-запроса к веб-сервису:

var MyCode = {
    req: new XMLHttpRequest(), // firefox only at the moment

    service_url: "http://url/to/Service.asmx",

    sayhello: function() {
        if (this.req.readyState == 4 || this.req.readyState == 0) {
            this.req.open("POST", this.service_url + '/HelloWorld', true);
            this.req.setRequestHeader('Content-Type','application/json; charset=utf-8');
            this.req.onreadystatechange = this.handleReceive; 
            var param = '{}';
            this.req.send(param);
        }
    },

    handleReceive: function() {
        if (this.req.readyState == 4) {
            // todo: using eval for json is dangerous
            var response = eval("(" + this.req.responseText + ")");
            alert(response);
        }
    }
}

Он вызывается с MyCode.sayhello (), конечно.

Проблема в том, что «req не определен» в первой строке функции handleReceive. Он вызывается 4 раза, поэтому я знаю, что приведенный выше код отправляет запрос на сервер.

Как я могу решить это?

Ответы [ 4 ]

5 голосов
/ 08 мая 2009

Классическая проблема закрытия. Когда вы получаете обратный вызов, замыкание фактически ссылается уже на объект HTTP.

Вы можете сделать следующее, как кто-то предлагает:

var that = this;
this.req.onreadystatechange = function() { this.handleReceive.apply(that, []); };

ИЛИ просто сделайте следующее:

var that = this;
this.req.onreadystatechange = function() { that.handleReceive(); };
2 голосов
/ 08 мая 2009

Вы можете решить это, сделав переменную, ссылающуюся на это в MyCode. Как

var MyCode = {
    req: new XMLHttpRequest(), // firefox only at the moment

    self = this

    ...
}

Тогда вместо этого вы можете обратиться к себе.

0 голосов
/ 08 мая 2009

вы должны быть в состоянии заставить его работать, изменив

this.req.onreadystatechange = this.handleReceive;

до

var that = this;
this.req.onreadystatechange = function() { this.handleReceive.apply(that, []); };

Function.prototype.apply может использоваться для вызова функции, в то время как явно this и аргументы функции.

0 голосов
/ 08 мая 2009

Изменить это:

this.req.onreadystatechange = this.handleReceive;

к этому:

var self = this;
this.req.onreadystatechange = function() { self.handleReceive(); }

Это создает закрытие, которое должно исправить ваши проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...