【问题标题】:How use setTimeout() with Backbone?如何将 setTimeout() 与 Backbone 一起使用?
【发布时间】:2013-01-07 23:55:44
【问题描述】:

如何在 Backbone 模型中使用 setTimeout()? 我有下一个代码:

var ContentModel = Backbone.Model.extend({
URL: "http://localhost/example.php",    
requestType: "POST",
dataType: "json",
data: "", //Set the value outside the model

startSend: function (Data) { 
           //
},
reply: function (Data) { 
    var dataJson = eval(Data);              
    console.log(dataJson);
    setTimeout(this.ajaxRequest(),4000);
},
problems: function (Data) { 
    //
},
ajaxRequest: function () {
    $.ajax({
        async:true,
        type: this.requestType,
        dataType: this.dataType, 
        url: this.URL,
        data: this.data,
        beforeSend:this.startSend,
        success: this.reply,
        timeout:4000,
        error:this.problems 
    });

}       

});

或者我已经尝试过:

setTimeout(function(){
               //ajax code
               },4000);

但结果是一样的。 setTimeout() 不起作用。该请求只运行一次。

【问题讨论】:

    标签: javascript jquery json backbone.js


    【解决方案1】:

    有几件事不对劲。首先,这一行:

    setTimeout(this.ajaxRequest(),4000);
    

    应该是:

    setTimeout(this.ajaxRequest, 4000);
    

    第一行代码执行ajaxRequest函数并将结果(即undefined)传递给setTimeout。这意味着ajaxRequest 函数将执行一次,但太快了。后一行做你想做的事,就是将函数本身传递给setTimeout,然后ajaxRequest会在4秒后被调用。

    但这还不够。执行ajaxRequest函数时,this上下文的值不正确。当您调用 setTimeout 时,回调的上下文设置为 window。您可以通过回调函数中的console.log(this) 来验证这一点。

    要修复它,您需要绑定函数的上下文。由于您使用的是 Backbone,因此您还已经加载了 underscore.js。使用_.bind 应该这样做:

    setTimeout(_.bind(this.ajaxRequest, this), 4000);
    

    编辑

    想一想,可能还有另一个问题。当 ajax 调用成功或失败时,replyproblems 函数可能会遭受与ajaxRequest 相同的上下文丢失。但如果有,它很容易修复。

    最简单的方法是在您的 Backbone 模型构造函数中调用 _.bindAll,而不是在这些上调用 _.bind

    initialize: function() {
      _.bindAll(this, 'ajaxRequest', 'reply', 'problems');
    }
    

    当您调用 _.bindAll 时,下划线保证每次调用您的模型中列出的任何方法时,this 上下文变量都会指向模型本身,除非特别绑定到其他东西。

    【讨论】:

    • 感谢您的回复。我已经理解了解释,使用 _.bindAll 代码有效,但 setTimeout 中的 _bind 无效
    • @vicenrele - 不客气。如果问题解决了,别忘了将答案标记为已接受。
    • 嗨@fencliff!你知道为什么下一个代码不起作用吗? setTimeout(function(){ this.ajaxRequest; },4000); 但是下一个:setTimeout(this.timeoutFunction,4000)
    • 另外,我试过这个:timeoutFunction: function(){ this.ajaxRequest; }, setTimeout(this.timeoutFunction,4000); 但不起作用
    • @vicenrele 这是因为匿名setTimeout回调函数内部this指的是window,而不是你的类。如果您需要确保保留上下文,请使用_.bind(func, this),如果还有更多问题,请考虑打开另一个问题。
    【解决方案2】:

    你不需要做任何特别的事情来使用setTimeout 和主干。在reply 函数中检查this 的范围。我猜this.ajaxRequest() 不在范围内。

    【讨论】:

      【解决方案3】:

      您必须改用setInverval

      setInterval(this.ajaxRequest, 4000);
      

      setTimeout 触发一次函数。

      setInterval 触发每个 n 毫秒。

      var interval = setInterval(this.ajaxRequest, 4000);
      

      clearInterval 用于清除setInterval

      clearInterval(interval);
      

      或者在你的ajax 上传递上下文参数:

      $.ajax({
          ...
          context: this,
          ...
      });
      

      【讨论】:

      • 嗯,其实他确实定义了this.reply作为ajax请求的成功回调,会再次触发该方法。
      • Ajax调用成功返回后会发生什么?
      • 什么都不会发生,因为this 上下文不正确。 thissetTimeout 回调中是窗口,除非绑定到别的东西。
      • @fencliff 我同意(见我的回答)
      • @fencliff,我的意图是在集合中创建具有此模型的视图时运行 setTimeout() 循环,如果从集合中删除模型,则 setTimeout() 不会运行。我有这个代码来删除模型:this.model.collection.remove(this.model);但是 setTimeout() 并没有停止工作。为什么?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-29
      • 1970-01-01
      • 1970-01-01
      • 2012-02-22
      • 2019-11-30
      • 2022-11-29
      相关资源
      最近更新 更多