Backbone中的同时fetch()失败

时间:2012-06-13 23:45:29

标签: javascript backbone.js coffeescript

我正在尝试实现对Backbone来说应该相对微不足道的东西,但是无法正常工作。我根据用户的操作填充了一系列图表。代码如下。

假设用户快速添加两个系列。或者一条路线同时发射两个系列。常量是在返回第一个fetch之前触发第二个fetch。在这种情况下,'fetching'被记录两次,但'fetched'只被记录一次。这是预期的行为,如果不是,我应该如何构建我的代码以使其工作?

# Series model
class Series extends Backbone.Model
    initialize: (options) ->
        _.bindAll @
        @endpoint = state?.getEndpoint()

    url: ->
        [localApiUrl, 'metrics', @endpoint, @.get('id')].join('/')



class SeriesCollection extends Backbone.Collection
    model: Series,

    initialize: ->
        _.bindAll @
        @bind 'add', @fetched

    fetchData: ( opts ) =>
        console.log('fetching')
        @series = new Series({ id: opts.id })
        @series.fetch
            success: (model, response) =>
                @.add({
                    id: @series.get('id')
                    name: @series.get('id')
                    data : @series.get('ts')
                    marker:
                        radius: 2
                    turboThreshold: 10000 
                    dataGrouping: 
                        enabled: false
                })

    fetched: () ->
        console.log('fetched', @)

1 个答案:

答案 0 :(得分:4)

将重复的模型添加到集合中并没有做任何事情;特别是,它不会触发"add"事件,因为不会添加任何内容。考虑一下:

# c is an empty collection
c.add(id: 1, t: 'where is')
c.add(id: 2, t: 'pancakes house?')
c.add(id: 1, t: 'different')

这将生成两个"add"个事件,该集合最终会以(1, 'where is')(2, 'pancakes house?')作为模型,第三个add将被忽略。

演示:http://jsfiddle.net/ambiguous/WUH6f/

0.9.2 changelog有这样说:

  
      
  • 在向集合中添加重复模型时,Backbone现在会默默地跳过它们,而不是抛出错误。
  •   

因此,如果fetchData被调用两次,您将获得两次console.log('fetching')的调用。但是,如果对opts.id的两次调用都fetchData相同,那么第二个@add将被忽略,因为集合中已经有id == opts.id的模型


你说opts.id每次都不同,但这并不一定意味着@series.get('id')会有所不同。请记住, AJAX 中的 A 代表异步,因此您可能会看到与此类似的一系列事件:

  1. 调用fetchData(id: 1)@series.id现在为1。
  2. 进行了AJAX调用。
  3. 调用fetchData(id: 2)@series.id现在为2.请记住,@series实例变量,而不是本地变量。
  4. 服务器从第一个AJAX调用返回,并触发success处理程序。 @series.id现在为2, 3 中的Series将被添加。
  5. 服务器从第二次AJAX调用返回,并触发成功处理程序。 @series.id仍为2,因此 3 中的Series将再次添加。但是这个会重复,所以add会忽略你。
  6. 你应该能够通过对问题系列使用普通的旧局部变量而不是实例变量来解决这个问题:

    fetchData: ( opts ) =>
        console.log('fetching')
        series = new Series({ id: opts.id })
        series.fetch
            success: (model, response) =>
                @add(
                    id: series.get('id')
                    #...
                )
    

    你不需要.中的@.add所以我把它拿出来了。我也放弃了@add电话中的大括号,因为你不需要它们;你也可以删掉括号,但我把它们留在了,因为我发现它们有助于澄清代码的块结构。

    我应该首先发现这个问题,对不起。