ember

Lessons learned from ember 0.9.8 to 1.12    window global
EAK
ember-cli
ember-data
. . .

chris hemp / @hemp

https://github.com/hemp/triangle-ember-06-15-2015

PureCloud Collaborate aka
Directory
OrgSpan Connect

Chat, Video, Phone Controls, Profiles, ...

semver and 6 week cadence

git-flow

ember-cliEmber App Kit

Controllers to Services

initializers and injections

Outlets vs alternatives

certain items are always available (left sidebar) - like chat

tearing down DOM

outlets are like ember-wormhole before ember-wormhole

listeners and external widgets

  • didInsertElement, willDestroyElement

implement destroy and also verify it does what it says it does

lingering document, window listeners?

Ember.run.scheduleOnce('afterRender', this, () => {})

let ns = `.${this.get('elementId')}`;
Ember.$(window).on(`resize.${ns}`, () => {}); Ember.$(window).off(ns);

chat - large lists

switching chat rooms was slow (1 second or more)

last September - leveraged coffeescript and string concatenation to reduce that to sub 50ms

breaks with glimmer

discourse did something similar but with a handlerbars helper that allowed plain handlerbars string generation

eric lifka's test repo

lodash.debounce vs Ember.run.debounce

_.debounce is on the prototype - applies to all instances

export var lodash = Ember.Object.extend({
    playSound: _.debounce(() => {
        this._playSound();
    }, 1000),
    _playSound: () => {}
});
export var ember = Ember.Object.extend({
    playSound: () => {
        Ember.run.debounce(this, this._playSound, 1000)
    },
    _playSound: () => {}
});

websocket event streams

Queue up objects necessary for render

Immediately return a promise for those objects

Drain and bulk load 'afterRender'

BatchDataRequestsMixin = Ember.Mixin.create
    peopleQueue: {
        'id-1': [promise, promise, ...]
        '...': [promises]
    }

    getPerson: (id) -> new Ember.RSVP.Promise (resolve) =>
        cachedModel = @store.getById 'person', id
        if cachedModel
            resolve cachedModel
        else
            queue = @get 'peopleQueue'
            queue[id] ?= []
            queue[id].push resolve
            @scheduleQueues()

    scheduleQueues: _.debounce ->
        Ember.run.scheduleOnce 'afterRender', @, ->
            people = @clearQueue 'peopleQueue'

            if not _.isEmpty(people)
                @processQueue 'person', people // -> store.findMany();
    , 500,
        maxWait: 5000

payload size

do you need all of your model now?

analytics

_debugContainerKey

Router.reopen({
    notifyGoogleAnalytics: function() {
        var a = this.container.lookup('service:analytics');
        a.pageView(this.get('url'));
    }.on('didTransition')
});

var analytics = container.lookup('service:analytics');
var record = function(analytics, actionName) {
    var args, containerKey, label;
    args = [].slice.call(arguments, 1);
    containerKey = this._debugContainerKey;//Private but so handy!

	label = void 0;
	if ((args != null ? args.length : void 0) > 0) {
		label = args.join(', ');
	}
    analytics.track(containerKey, actionName, label);
};
Ember.ActionHandler.reopen({
    send: function(actionName) {
        var args;
        args = [].slice.call(arguments, 1);
        record.apply(this, [analytics, actionName].concat(args));
        return this._super.apply(this, [actionName].concat(args));
    }
});

pr reviews

observers are synchronous

docs

ember.run.*

docs

ember.computed.*

docs

DS.RESTADAPTER.coalesceFindRequests

coalesceFindRequests

others?

Ember at ININ and PureCloud

Collaborate

Sign-up

Document Viewer

OAuth (in progress)

Thanks!

psst...come and make sweet ember with us