Move away from observers?

We are struggling with how to transition away from observers in our Ember app.

For this case we have a 3rd party WebRTC library that starts when we call startStream. We cannot start the stream before status is 'live' and isConnected is true After refactoring away observers this is what we came up with:

  _status: null,
  status: computed({
    set(key, value) {
      const status = value.value
      this.set('_status', status)
      const isConnected = this.get('isConnected')
      this.handleStream(isConnected, status)
      return status
    },
    get() {
      return this.get('_status')
    }
  }),

  _isConnected: false,
  isConnected: computed({
    set(key, value) {
      this.set('_isConnected', value)
      const status = this.get('status')
      this.handleStream(value, status)
      return value
    },
    get() {
      return this.get('_isConnected')
    }
  }),

  handleStream(isConnected, status) {
    if (!isConnected) return
    if (status === 'live') {
      this.startStream()
    } 
  }

The old way:

handleStream: observer('liveStream.status', 'isConnected', function() {
    if (!this.get('isConnected')) return
    if (this.get('status') === 'live') {
      this.startStream()
    } 
  })

The old way with an observer just looks so much shorter and easier to follow. Are we missing some better way of doing this?

Thanks!

I think that using observers to propagate ember state changes to external code is reasonable - it’s using observers to just change ember state that’s encouraged to avoid as fair as I’m aware.

I think you could make this work nicely with a modifier, preferably a custom one implemented using ember-modifier. If the following doesn’t work, I believe I’ve misunderstood your example!

import { modifier } from 'ember-modifier';

export default modifier((_el, _positional, { liveStream, isConnected, start }) => {
  if (!isConnected) return
  if (liveStream.status === 'live') {
    start()
  }
});
<div
  {{handleStream
    @liveStream=@liveStream
    @isConnected=this.isConnected
    @start=this.startStream
  }}
/>
  {{! the body of your component }}
</div>
1 Like

@alexspeller is right, this is actually the perfect use case for observers and it’s why they’re not deprecated. They’re the right tool for propagating ember state into non-ember code.

@chriskrycho Thanks for the suggestion! It could possibly work but I think its actually clearer to keep it out of the DOM. I think I actually favor the computed property dance above in that case for clarity and no need for another library.

@ef4 @alexspeller Thanks for clarifying, it helps out a lot! It was the warnings from the linter that made me stumble down this rabbit hole in the first place: eslint-plugin-ember/no-observers.md at master · ember-cli/eslint-plugin-ember · GitHub