由于对象可见性,封装ajax调用失败

时间:2011-12-01 03:51:11

标签: javascript ajax

我有这段代码可以在Firefox 3.6上运行。问题是应该定义到STEP2并在STEP3上使用的变量this.xmlhttp就像STEP2和STEP3上的代码在不同的变量环境中一样,即使我希望server_request和callback_function中的2个用法指向同一个成员query_request_manager中的对象superobject定义较低。我还创建了类似的代码,在服务器响应时没有异步回调,因为我打算使用它。

function Generic_server_request(server_location, server_file, client_callback_function)
{
    this.server_location = server_location;
    this.server_file = server_file;
    this.query_parameters = "";
    this.client_callback_function = client_callback_function;
    this.xmlhttp = undefined;
} // STEP1 should create xmlhttp as undefined

Generic_server_request.prototype.callback_function = function ()
{
    if (this.xmlhttp.readyState === 4 // STEP3 ERROR this.xmlhttp is undefined
    // I expected it to be the object defined at STEP2
    // but it's not so according to firebug
    // similar code without asynchronous callback
    // seems to work as I expect it to : no undefined error
    && this.xmlhttp.status === 200)
    {
        this.client_callback_function(
        this.xmlhttp.responseText);
    }
    else if (this.xmlhttp.status !== 200 || (this.xmlhttp.status === 200 && this.xmlhttp.readyState !== 2 && this.xmlhttp.readyState !== 3))
    {
        alert("readystate " + this.xmlhttp.readyState + " status " + this.xmlhttp.status);
    }
};

Generic_server_request.prototype.server_request = function ()
{
    this.xmlhttp = new XMLHttpRequest(); // STEP2 xmlhttp defined for use
    this.xmlhttp.onreadystatechange = this.callback_function; // server callback to prototype.callback
    this.xmlhttp.open("GET", this.server_location + this.server_file + this.query_parameters, true);
    this.xmlhttp.send();
};

Generic_server_request.prototype.set_query_parameters = function (query_parameters)
{
    this.query_parameters = query_parameters;
};

var query_request_manager;

function do_querry()
{
    server_querry("test");
}

function server_querry(input)
{
    if (query_request_manager === undefined)
    {
        query_request_manager = new Generic_server_request( // the definition
        "http://localhost/cgi-bin/", "querry_handler.php", status_text);
    }
    query_request_manager.set_query_parameters("?input=" + input);
    query_request_manager.server_request();
} // the usage

//end javascript

<input type="button" value="Enter" onclick="do_querry();" />

2 个答案:

答案 0 :(得分:2)

问题是这个任务:

this.xmlhttp.onreadystatechange = this.callback_function;

将this.callback_function定义的函数赋值给onreadystatechange,但是没有将其作用域绑定到query_request_manager(这意味着在执行回调时它将绑定到全局作用域,而不是你想要的对象)。要解决此问题,您可以使用委托功能:

this.xmlhttp.onreadystatechange = (function () {
    var me = this;
    return function () {
       return me.callback_function.apply(me, arguments);
    }
}).call(this);

答案 1 :(得分:0)

试试这个:

var Generic_server_request = function(server_location, server_file, client_callback_function){
  this.server_location = server_location;
  this.server_file = server_file;
  this.query_parameters = "";
  this.client_callback_function = client_callback_function;
  this.xmlhttp = undefined; // STEP1 should create xmlhttp as undefined
}

Generic_server_request.prototype.callback_function = function(){
  if(this.xmlhttp.readyState === 4 && this.xmlhttp.status === 200){ // STEP3 ERROR this.xmlhttp is undefined
    // I expected it to be the object defined at STEP2
    // but it's not so according to firebug
    // similar code without asynchronous callback
    // seems to work as I expect it to : no undefined error
    this.client_callback_function(this.xmlhttp.responseText);
  } else if(this.xmlhttp.status!==200 || (this.xmlhttp.status===200 && this.xmlhttp.readyState!==2 && this.xmlhttp.readyState!==3)){
    alert("readystate " + this.xmlhttp.readyState + " status " + this.xmlhttp.status);
  }
};
Generic_server_request.prototype.server_request=function(){
  this.xmlhttp = new XMLHttpRequest(); // STEP2 xmlhttp defined for use
  this.xmlhttp.onreadystatechange = this.callback_function; // server callback to prototype.callback
  this.xmlhttp.open("GET", this.server_location + this.server_file + this.query_parameters, true);
  this.xmlhttp.send();
};
Generic_server_request.prototype.set_query_parameters = function(query_parameters){
  this.query_parameters = query_parameters;
};
var query_request_manager; 

function do_querry(){
  server_querry("test");
}
function server_querry(input){
  if(query_request_manager === undefined){
    query_request_manager = new Generic_server_request("http://localhost/cgi-bin/", "querry_handler.php", status_text);
  }
  query_request_manager.set_query_parameters("?input=" + input);
  query_request_manager.server_request();
}


<input type="button" value="Enter" onclick="do_querry();" />