【问题标题】:XMLHttpRequest and Binding a Callback not workingXMLHttpRequest 和绑定回调不起作用
【发布时间】:2017-11-27 19:28:24
【问题描述】:

我有一个简单的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当前 值执行,在这个阶段,它什么都不是。

如果我需要以 future 值作为响应,第一个版本似乎更可取。

谢谢大家。

【问题讨论】:

  • 当你执行 .bind(xhr,xhr.response) 时还没有任何响应 -> xhr.response === undefined

标签: javascript ajax callback xmlhttprequest function-binding


【解决方案1】:

这是因为callback.bind 会立即执行。而在它执行的时候,xhr.responseText 显然是不可用的,因为请求还没有完成。你可以试试这个看看效果。

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

【讨论】:

    【解决方案2】:

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

    这是一个简单的代码sn-p:

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

    打印结果为:AAA,因为a.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' }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-07
      • 2018-04-11
      • 2013-08-04
      • 1970-01-01
      相关资源
      最近更新 更多