2

我有一个简单的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 调用的响应。

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

  1. 版本 1 只是在事件处理函数内部调用回调。
  2. 版本 2 用于bind做同样的事情;this设置为xhr对象,而xhr.response作为参数发送。

当我使用版本 1 时,一切都按预期工作。当我使用版本 2 时,data参数为空。

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

评论

感谢答案,我想我有它。

.bind()立即以 的当前值执行xhr.responseText,在这个阶段,它什么都不是。

如果我需要用未来值做出回应,似乎第一个版本更可取。

谢谢大家。

4

2 回答 2

1

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

function doit(data) {
    alert(data, this.responseText);
}
于 2017-06-24T09:19:02.580 回答
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);
});

打印的结果是:AAA, asa.display被绑定并且a.display是一个原始类型(字符串)——绑定时刻的值(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' }

于 2017-06-24T09:43:03.427 回答