更新 Backbone 模型/视图的轮询请求

15
我需要找到一种更新使用backbone实现的Web应用程序的方法。使用案例如下:
我有几个视图,每个视图或与此视图相关的模型/集合,需要在不同的时间向服务器发出不同的轮询请求以发现某些更改。
我想知道最常见的实现方式是什么:
1)实现“传统轮询请求”
2)实现“长轮询请求”
3)实现“HTML5 web socket”
P.S .:
1)服务器是用PHP编写的。
2)目前我正在寻找一种无需使用HTML5 WebSockets的解决方案,因为可能在PHP中并不简单。
这是我使用“传统轮询请求”的简单代码(1)。
// MyModel
var MyModel = Backbone.View.extend({
    urlRoot: 'backendUrl'
});

// MyView
var MyView = Backbone.View.extend({

    initialize: function () {
        this.model = new MyModel();
        this.model.fetch();
        this.model.on('change', this.render);
        setTimeout(function () {
            this.model.fetch();
        }, 1000 * 60 * 2); // in order to update the view each two minutes
    }
});


如果你熟悉 ASP.NET,那么可以尝试一下 SignalR,它让客户端和服务器之间的交互变得非常容易,而且能够根据浏览器的能力自动选择适当的连接模型。 - Alexander
WebSocket在PHP中的应用。虽然作者称它为旧代码并快速打了补丁,但仍值得一看。http://code.google.com/p/phpwebsocket/source/browse/#svn%2Ftrunk%2F%20phpwebsocket - Kinjal Dixit
WebSocket在PHP中更加有前途:http://code.google.com/p/phpws/source/browse/#git%2Fphpws - Kinjal Dixit
3个回答

18

在您的模型中实现轮询处理程序,可以参考以下示例:

// MyModel
var MyModel = Backbone.Model.extend({
  urlRoot: 'backendUrl',

  //Add this to your model:
  longPolling : false,
  intervalMinutes : 2,
  initialize : function(){
    _.bindAll(this);
  },
  startLongPolling : function(intervalMinutes){
    this.longPolling = true;
    if( intervalMinutes ){
      this.intervalMinutes = intervalMinutes;
    }
    this.executeLongPolling();
  },
  stopLongPolling : function(){
    this.longPolling = false;
  },
  executeLongPolling : function(){
    this.fetch({success : this.onFetch});
  },
  onFetch : function () {
    if( this.longPolling ){
      setTimeout(this.executeLongPolling, 1000 * 60 * this.intervalMinutes); // in order to update the view each N minutes
    }
  }
});

// MyView
var MyView = Backbone.View.extend({

    initialize: function () {
        this.model = new MyModel();
        this.model.startLongPolling();
        this.model.on('change', this.render);
    }
});

这实际上是长轮询吗,还是你只是用了那个词?我的理解是,在长轮询中,您打开一个与服务器的单个连接并等待响应。这看起来只是连续轮询。 - Ziggy
@Ziggy,你对技术的定义有误。"打开单个连接"技术被称为"推送技术"。长轮询请求"模拟"了"推送技术",用于那些无法使用套接字连接(由推送使用)的情况。长轮询请求通过随时向服务器询问更新来模拟它。 - Daniel Aranda
@DanielAranda 谢谢!那么,在这种情况下,你会如何实现与“长轮询”不同的“轮询”呢? - Ziggy
1
对于客户端代码而言是相同的。正常轮询和长轮询之间的区别在于服务器代码。轮询和长轮询之间的区别在于,如果答案为空,正常轮询将尽快返回它,但长轮询可能会等待一段时间。例如,一个仅使用轮询的聊天后端代码将在您发出请求后立即返回一个数组,而长轮询可能会等待几秒钟以查看是否出现消息。@Ziggy - Daniel Aranda
如何停止这个轮询? - vini
显示剩余3条评论

11

我不确定你在这里问的是什么,但这是我的一些想法:

1) 你的代码似乎与标题中写的相矛盾。使用setTimeout(或setInterval)进行持续轮询与长轮询不同。实际上,它是常规轮询。区别在于,使用长轮询时,客户端启动一个AJAX请求并等待。服务器决定何时响应。只有当有新数据可用时,它才应该响应。并且在响应后立即启动新的轮询请求。

:创建(相对)高效的长轮询服务器不是一项简单的任务,请注意。

2) 你如何处理客户端(即长轮询逻辑放在哪里)并不重要,只要你知道自己的代码内部发生了什么就行。当然,要记住,也许将来你希望对代码进行一些更改,因此将其保持独立可能是最好的选择。这是我会选择的架构:

  • 独立脚本创建全局的EventManager对象(该脚本应该作为第一个加载)。这样的对象将具有以下方法:.bind.trigger,它将管理事件。 :) 例如,以下是实现的示例:

在自己的对象中实现事件

  • 独立的脚本处理长轮询。每当从服务器接收到数据时(即AJAX长轮询请求最终结束),它会调用EventManager.trigger('long_polling_data', res);。然后你需要在你的Backbone视图或任何你喜欢的地方绑定到此事件。

顺带一提:这种架构的额外奖励是,如果您决定切换到WebSockets或任何其他技术(例如:JSONP轮询),那么您只需要实现其他技术的逻辑。主要代码将仅使用long_polling_data事件,因此不需要进行其他更改(您可能需要更改事件的名称:])。

3) 尽管您说您不想使用WebSockets,但我必须对此发表评论。:)你知道世界在不断发展。你应该忘记长轮询技术。使用WebSockets和XMLSocket(也称为FlashSocket)作为备用方案更有效,并且实现服务器端更加简单。

希望我能有所帮助,抱歉如果有语言错误,祝您的项目好运!


1
谢谢您的回复。我已经将我的问题标题从“长轮询”更改为“传统轮询”。 - Lorraine Bernard
我添加了更多关于我的问题的细节。也许这可以帮助您给我更多关于如何使用webSocket的信息。谢谢。 - Lorraine Bernard
抱歉,我不是PHP开发人员,无法帮助您解决问题。除非您愿意学习Python或服务器端JavaScript。:] 现在想想,对于一个经验不足的开发人员来实现长轮询和/或Websockets可能有些困难。如果您不会进行大量请求,那么普通轮询也可以正常工作。而且这很容易实现,只需使用setTimeout即可。 - freakish

2
我知道你在问题中表示你不想使用php进行Websockets(因为这并不简单),但是,我发现这相对来说还是比较简单的。
以下是步骤:
1. 我使用了一个带有回退功能的Websockets应用程序http://pusher.com/。(顺便说一下,我与该公司没有联系)。
2. 在服务器/ api上包含https://github.com/squeeks/Pusher-PHP
3. 在客户端上包含<script src="http://js.pusherapp.com/1.12/pusher.min.js"></script>
客户端和服务器通道可以设置为使用Websockets相互通信。

感谢您的回复。pusher-php 看起来非常有趣。 - Lorraine Bernard
pusher-php 看起来非常有趣,但我必须付费! - Lorraine Bernard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接