Javascript 重写.fetch()可以处理假数据、urlRoot错误和实际模型ajax请求

Javascript 重写.fetch()可以处理假数据、urlRoot错误和实际模型ajax请求,javascript,model-view-controller,backbone.js,coffeescript,marionette,Javascript,Model View Controller,Backbone.js,Coffeescript,Marionette,我很困惑——我以为我的模型绑定工作正常,但它只是作为一个JSFIDLE和伪造的ajax请求。我已经将一个模型绑定到一个视图,如果我重写.fetch()并伪造响应,一切都会正常工作(我可以在页面上更新模型和视图)。但是,当我不重写.fetch()并使用urlRoot参数并等待响应时,就会出现错误 以下是正在工作的JSFIDLE,其中模型在调用.fetch()并使用伪造响应后呈现,而不是更改: 因此,如果我在服务器端有一个API调用: /thing/:id 通过对/thing/1的示例响应: {"

我很困惑——我以为我的模型绑定工作正常,但它只是作为一个JSFIDLE和伪造的ajax请求。我已经将一个模型绑定到一个视图,如果我重写
.fetch()
并伪造响应,一切都会正常工作(我可以在页面上更新模型和视图)。但是,当我不重写
.fetch()
并使用
urlRoot
参数并等待响应时,就会出现错误

以下是正在工作的JSFIDLE,其中模型在调用
.fetch()
并使用伪造响应后呈现,而不是更改:

因此,如果我在服务器端有一个API调用:

/thing/:id

通过对
/thing/1
的示例响应:

{"id":"1","latitude":"lat1","longitude":"lon1"} 
如果我注释掉
.fetch()
,就会得到控制台错误:

load js core functions core.js:2
init model timeout app.js:114
initializer callback for history, routes app.js:95
App.Layouts.MyLayout onShow app.js:41
App.Regions.MyRegion onShow app.js:25
App.Models.Thing init app.js:55
App.ItemViews.Thing init app.js:87
Uncaught TypeError: Object #<Object> has no method 'toJSON' backbone.marionette-0.8.1.min.js:9
Parsing App.Models.Thing.fetch() response: {"id":"1","latitude":"lat1","longitude":"lon1"} app.js:62
Thing: {"id":"1","latitude":"lat1","longitude":"lon1"} app.js:66
a Thing has changed, update ItemView! app.js:57

Uncaught TypeError: Cannot call method 'render' of undefined app.js:58

update model app.js:108

Uncaught TypeError: Object #<Object> has no method 'set' 

这里发生了很多奇怪和混乱的事情。不要害怕,一切还没有失去,混乱可以解决

主干网应该返回一个
jqXHR
,而不是模型本身。您的
fetch
实现错误地返回了
@parse resp
,并且返回了
@
(这也是不正确的,有时两个错误就是正确的)。结果是:

App.Data.thing = new App.Models.Thing(id: 1).fetch()
当您使用
fetch
时,会为您提供一个有用的
App.Data.thing
,但主干
fetch
不适用。因此,您的
fetch
已损坏,并且您没有正确使用
fetch
;然后尝试将
jqXHR
作为模型提供给视图,视图在
jqXHR
而不是模型上设置
@view

initialize: (options) ->
  #...
  @options.model.view = @
initialize: (options) ->
    @model.on('change', @render)
因此,您在
jqXHR
上得到了一个
view
属性,但是模型没有
@view
(因为
App.Data.thing
不是模型),并且您在模型的更改处理程序中得到了一个“无法调用未定义的“render”方法”错误

您应该这样做:

App.Data.thing = new App.Models.Thing(id: 1)
App.Data.thing.fetch()
现在转到您的
分析

parse: (resp) ->
  console.log 'Parsing App.Models.Thing.fetch() response: ' + JSON.stringify resp
  @attributes.id = resp.id
  @attributes.latitude = resp.latitude
  @attributes.longitude = resp.longitude
  console.log 'Thing: ' + JSON.stringify @
  @
从:

每当服务器在fetch和save中返回模型数据时,都会调用parse。函数被传递给原始
响应
对象,并应返回要在模型上设置的属性散列

因此,
parse
应该只是将服务器的响应传递到模型上。您的
parse
正在设置属性并返回
@
。结果是,您最终将执行与
m.set(m)
等效的操作。所以,摆脱你的
parse
实现,你的实现是不正确的,你甚至不需要它

您的模型/视图连接是反向的:视图引用模型,模型不引用视图。您的模型中包含以下内容:

initialize: (item) ->
  console.log 'App.Models.Thing init'
  @bind 'change', ->
    console.log 'a Thing has changed, update ItemView!'
    @view.render()
在你看来:

initialize: (options) ->
  console.log 'App.ItemViews.Thing init'
  # Bind
  @options.model.view = @
您应该在创建模型时将模型传递给视图(您可以这样做,这样就可以了):

然后视图应绑定到模型:

initialize: (options) ->
  #...
  @options.model.view = @
initialize: (options) ->
    @model.on('change', @render)
您可以在模型中删除
初始化
实现

此外,您可以(也应该)直接在命名空间中声明类,但不要这样做:

class Thing extends Backbone.Marionette.ItemView
  #...
App.ItemViews.Thing = Thing
setTimeout 'App.updateModel()', 2000
这样做:

class App.ItemViews.Thing extends Backbone.Marionette.ItemView
  #...
setTimeout (-> App.updateModel()), 2000
此外,几乎不应该使用is-evil的string/eval形式。不要这样做:

class Thing extends Backbone.Marionette.ItemView
  #...
App.ItemViews.Thing = Thing
setTimeout 'App.updateModel()', 2000
这样做:

class App.ItemViews.Thing extends Backbone.Marionette.ItemView
  #...
setTimeout (-> App.updateModel()), 2000

可能还有更多,但希望这能让你开始并解决眼前的问题。

这里发生了很多奇怪和困惑的事情。不要害怕,一切还没有失去,混乱可以解决

主干网应该返回一个
jqXHR
,而不是模型本身。您的
fetch
实现错误地返回了
@parse resp
,并且返回了
@
(这也是不正确的,有时两个错误就是正确的)。结果是:

App.Data.thing = new App.Models.Thing(id: 1).fetch()
当您使用
fetch
时,会为您提供一个有用的
App.Data.thing
,但主干
fetch
不适用。因此,您的
fetch
已损坏,并且您没有正确使用
fetch
;然后尝试将
jqXHR
作为模型提供给视图,视图在
jqXHR
而不是模型上设置
@view

initialize: (options) ->
  #...
  @options.model.view = @
initialize: (options) ->
    @model.on('change', @render)
因此,您在
jqXHR
上得到了一个
view
属性,但是模型没有
@view
(因为
App.Data.thing
不是模型),并且您在模型的更改处理程序中得到了一个“无法调用未定义的“render”方法”错误

您应该这样做:

App.Data.thing = new App.Models.Thing(id: 1)
App.Data.thing.fetch()
现在转到您的
分析

parse: (resp) ->
  console.log 'Parsing App.Models.Thing.fetch() response: ' + JSON.stringify resp
  @attributes.id = resp.id
  @attributes.latitude = resp.latitude
  @attributes.longitude = resp.longitude
  console.log 'Thing: ' + JSON.stringify @
  @
从:

每当服务器在fetch和save中返回模型数据时,都会调用parse。函数被传递给原始
响应
对象,并应返回要在模型上设置的属性散列

因此,
parse
应该只是将服务器的响应传递到模型上。您的
parse
正在设置属性并返回
@
。结果是,您最终将执行与
m.set(m)
等效的操作。所以,摆脱你的
parse
实现,你的实现是不正确的,你甚至不需要它

您的模型/视图连接是反向的:视图引用模型,模型不引用视图。您的模型中包含以下内容:

initialize: (item) ->
  console.log 'App.Models.Thing init'
  @bind 'change', ->
    console.log 'a Thing has changed, update ItemView!'
    @view.render()
在你看来:

initialize: (options) ->
  console.log 'App.ItemViews.Thing init'
  # Bind
  @options.model.view = @
您应该在创建模型时将模型传递给视图(您可以这样做,这样就可以了):

然后视图应绑定到模型:

initialize: (options) ->
  #...
  @options.model.view = @
initialize: (options) ->
    @model.on('change', @render)
您可以在模型中删除
初始化
实现

此外,您可以(也应该)直接在命名空间中声明类,但不要这样做:

class Thing extends Backbone.Marionette.ItemView
  #...
App.ItemViews.Thing = Thing
setTimeout 'App.updateModel()', 2000
这样做:

class App.ItemViews.Thing extends Backbone.Marionette.ItemView
  #...
setTimeout (-> App.updateModel()), 2000
此外,几乎不应该使用is-evil的string/eval形式。不要这样做:

class Thing extends Backbone.Marionette.ItemView
  #...
App.ItemViews.Thing = Thing
setTimeout 'App.updateModel()', 2000
这样做:

class App.ItemViews.Thing extends Backbone.Marionette.ItemView
  #...
setTimeout (-> App.updateModel()), 2000

可能还有更多,但希望这能让你开始并解决眼前的问题。

有用、措辞恰当、有趣。谢谢乐于助人,措辞得体,f