XMLHttpRequest和绑定回调无效

时间:2017-06-24 08:46:39

标签: javascript ajax callback xmlhttprequest function-binding

我有一个使用get的简单XMLHttpRequest函数,它接受一个回调参数。计划是在onload事件处理程序上调用回调。

这是一个简化版本:

get(url,doit);

function doit(data) {
    alert(data)
}
function post(url,callback) {
    var xhr=new XMLHttpRequest();
    xhr.onload=function() {                     //  Version 1
        callback(xhr.response)
    }
    xhr.onload=callback.bind(xhr,xhr.response); //  Version 2
    xhr.open('get',url,true);
    xhr.send(data);
}

回调函数有一个参数data,它应该是来自Ajax调用的响应。

我有两个版本的调用回调:

  1. 版本1只调用事件处理函数内的回调。
  2. 版本2使用bind来做同样的事情; this设置为xhr对象,xhr.response作为参数发送。
  3. 当我使用版本1时,一切都按预期工作。当我使用版本2时,data参数为空。

    我以为我知道XMLHttpRequest.bind()相当不错,但我无法解释为什么第二个版本是空的。这里发生了什么(不)?

    注释

    感谢答案,我想我已经拥有了。

    .bind()会立即执行当前xhr.responseText,在此阶段,该值为空。

    如果我需要回复 future 值,那么第一个版本似乎更合适。

    谢谢大家。

2 个答案:

答案 0 :(得分:1)

这是因为callback.bind将立即执行。并且在执行时,xhr.responseText显然不可用,因为请求尚未完成。您可以尝试这样来查看结果。

function doit(data) {
    alert(data, this.responseText);
}

答案 1 :(得分:0)

这是bind的行为:当参数绑定时,绑定值是引用的对象,或者当时的原始值。

这是一个简单的代码段:

function operate(callback) {
  let a = {
    display: 'AAA'
  };
  setTimeout(callback.bind('ThisObj', a.display), 1000);
  a.display = 'AAA222';
}

operate(function(data) {
  console.log(data);
});

打印结果为:AAAa.display为绑定,a.display为基本类型(String) - 绑定时刻的值(AAA)通过了。

这就是xhr.response发生的事情,因为它的类型是字符串。

但是,如果一个对象作为参数绑定,那么该对象的引用将被传递,这意味着绑定的函数将获得最新的值:

function operate(callback) {
  let tmp = {
    t: 'AAA'
  };
  let a = {
    display: tmp
  };
  setTimeout(callback.bind('ThisObj', a.display), 1000);
  tmp.t = 'AAA222';
}

operate(function(data) {
  console.log(data);
});

打印结果为:{ t: 'AAA222' }

请注意:如果上例中的变量a将其值更改为另一个对象,则绑定的参考值不会更改(仍然是之前引用的对象):

function operate(callback) {
  let a = {
    display: 'AAA'
  };
  setTimeout(callback.bind('ThisObj', a), 1000);
  a = {
    display: 'AAA222'
  };
}

operate(function(data) {
  console.log(data);
});

打印结果为:{ display: 'AAA' }