简体   繁体   English

Backbone Model有条件地触发事件,View不会听到它

[英]Backbone Model triggers event conditionally, View doesn't hear it

I'm creating a Geolocation Model, fetching from localStorage, and checking if I have there is a latitude property there. 我正在创建一个地理定位模型,从localStorage获取,并检查我是否有纬度属性。 If there isn't, a 'geolocation:city_state_blank' event is triggered. 如果没有,则触发'geolocation:city_state_blank'事件。 If 'geolocation:city_state_blank' is heard, @get_users_geolocation() is fired. 如果听到'geolocation:city_state_blank'@get_users_geolocation()触发@get_users_geolocation()

class App.GeoLocation extends Backbone.Model
    initialize: ->

       @on 'geolocation:city_state_blank', -> @get_users_geolocation()

       @fetch().always => 
         if @get('city_state').length is 0
           @trigger 'geolocation:city_state_blank'
         else
           @trigger('geolocation:done')




    get_users_geolocation: =>
        # Code to get / save (in localStorage) a users geolocation and city / state
        @trigger('geolocation:done')

After get_users_geolocation() is done the event geolocation:done is triggered. 完成get_users_geolocation()之后,触发事件geolocation:done

I've removed details of fetching the users geoLocation / reverse Geolocation lookups, which are all asynchronous. 我已经删除了获取用户geoLocation / reverse Geolocation查找的详细信息,这些查找都是异步的。 But the end result of all that work boils down to triggering the geolocation:done event. 但是所有这些工作的最终结果归结为触发geolocation:done事件。

class App.GeolocationView extends Backbone.View
   initialize: =>
      @listenTo @model, 'geolocation:done', =>
        alert('geolocation:done was heard in the view!!!!')

Here is the problem: 这是问题所在:

In the scenario when the Geolocation model fetches from localStorage and determines the property latitude is not set , and thus calls get_users_geolocation — the View alerts geolocation:done was heard in the view!!!! 在Geolocation模型从localStorage获取并确定未设置属性latitude情况下,因此调用get_users_geolocation - 视图警报地理位置:在视图中听到完成!!!!

But in the scenario when Geolocation has a latitude property (the else), and triggers the geolocation:done right away, the View does not alert anything. 但是在Geolocation具有纬度属性(else)并触发geolocation:done ,View 不会发出任何警报。 The view doesn't hear it. 视图没有听到。

I've console.logged the hell out of this, and can say the flow paths are working. 我已经控制了。记住了这个地狱,并且可以说流路正在运行。 The if/else are working and the View is getting instantiated correctly. if / else正在运行,View正在被正确实例化。 Logging within the callback after fetching from localStorage yields this.. 从localStorage获取后在回调中记录产生这个..

@fetch().always => 
    console.log @get('current_city_state')
    console.log typeof @get('current_city_state')
    // Norfolk, VA
    // String

So, there is data there.. 那么,那里有数据..

What is going on?? 到底是怎么回事?? Help please!! 请帮助!!

I'd guess that the latitude property of your App.GeoLocation is a single number. 我猜你的App.GeoLocationlatitude属性是一个数字。 That would leave your test looking like this: 这会让你的测试看起来像这样:

if some_number.length is 0

Numbers don't have length properties so @get('latitude').length will be undefined and you're left with: 数字没有length属性,所以@get('latitude').length将是未定义的,你留下:

if undefined is 0

That will always be false so @trigger('geolocation:done') always gets called. 这总是假的,所以@trigger('geolocation:done')总是被调用。

If you're interested in the existence of the latitude property, then CoffeeScript's existential operator ( ? ) will server you better: 如果您对latitude属性的存在感兴趣,那么CoffeeScript的存在运算符( ? )将为您提供更好的服务:

if @get('latitude')?
    # There is a latitude.
else
    # No latitude.

To see how ? 看怎么样? behaves you could have a look at what this does: 表现你可以看看这是做什么的:

class M extends Backbone.Model

m = new M(p: 0)

if m.get('p') == 0
    console.log('p == 0')
else
    console.log('p != 0')
if m.get('p')?
    console.log('there is a p')
else
    console.log('the p is a lie')
if m.get('no')?
    console.log('yes no')
else
    console.log('no no')    

That will give you p == 0 , there is ap , and no no . 这将给你p == 0there is apno no

Demo: http://jsfiddle.net/ambiguous/qmBNy/ 演示: http//jsfiddle.net/ambiguous/qmBNy/

I ended up doing this. 我最终这样做了。 It aint pretty, but it works. 它不漂亮,但它的工作原理。

@listenTo @model, 'geolocation:done', =>        
   @prefill_location_input()
   @initialize_autocomplete()

@prefill_location_input()
@initialize_autocomplete()

I think that your right, the event is triggered before init returns. 我认为你的权利,事件是在init返回之前触发的。 Here, if Object is ready right away, the @prefill_location_input() and @initialize_autocomplete() are called, geolocation:done will overwrite it in cases its fetched from the network. 这里,如果Object立即就绪,则@prefill_location_input()@initialize_autocomplete()geolocation:done将在从网络中获取的情况下覆盖它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM