Last active
October 28, 2018 09:36
-
-
Save machty/985d62c51ff651f65f4aab67ea994eb4 to your computer and use it in GitHub Desktop.
New Twiddle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Ember from 'ember'; | |
import { lifespan, subscription } from "../subscription"; | |
import { bind } from '@ember/runloop'; | |
import { task, timeout } from 'ember-concurrency'; | |
export default Ember.Controller.extend({ | |
chatRooms:[ "EmberChat", "ReactChat", "VueChat", "AngularChat"], | |
chatRoom: null, | |
// chatRoomName: null, | |
// goal: it should be easy to do `.not()` and tap into preexisting CP macros | |
chatRoomLifespan: lifespan('chatRoomName', function(chatRoomName) { | |
return { key: chatRoomName, value: chatRoomName }; | |
}), | |
chatRoomSubscription: subscription('chatRoomLifespan', function(chatRoomName) { | |
let intervalId = setInterval(bind(() => { | |
this.log(`${chatRoomName}: chatRoomSubscription says: ${Math.round(Math.random() * 5000)}`); | |
}), 500); | |
return () => clearInterval(intervalId); | |
}), | |
chatTask: task(function * (chatRoomName) { | |
while(true) { | |
yield timeout(300 + 500 * Math.random()) | |
this.log(`${chatRoomName}: chatTask says: ${Math.round(Math.random() * 5000)}`); | |
} | |
}).aliveWithin('chatRoomLifespan'), | |
messages: [], | |
log(message) { | |
let messages = this.messages.slice(0, 20); | |
messages.unshift(message); | |
this.set('messages', messages); | |
}, | |
actions: { | |
changeChatRoomName(name, e) { | |
e.preventDefault(); | |
this.set('chatRoom', { name }); | |
} | |
}, | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ComputedProperty from '@ember/object/computed'; | |
import { addListener } from '@ember/object/events'; | |
import { addObserver } from '@ember/object/observers'; | |
class SubscriptionManager extends ComputedProperty { | |
constructor(subscriptionConstructor, dependentKeys) { | |
function getter(propName) { | |
let hostObject = this; | |
let currentSubscriptionKey = `_${propName}`; | |
let currentSubscription = hostObject[currentSubscriptionKey]; | |
let newValues = dependentKeys.map(key => hostObject[key]); | |
let newKey = newValues.join(newValues.join(';')); | |
let currentKey = currentSubscription && currentSubscription.key || "perfect is the enemy of perfectly adequate"; | |
if (newKey === currentKey) { | |
return currentSubscription.value; | |
} else if (newKey !== currentKey) { | |
if (currentSubscription && currentSubscription.dispose) { currentSubscription.dispose(); } | |
let value = subscriptionConstructor.apply(hostObject, newValues); | |
let newSubscription; | |
// it should be possible to return | |
if (value) { | |
if (typeof value === 'function') { | |
newSubscription = { dispose: value, value: true }; | |
} else if (typeof value.dispose === 'function') { | |
newSubscription = { dispose: () => value.dispose(), value }; | |
} else if (typeof value.cancel === 'function') { | |
// ember-concurrency hacks: a TaskInstance can be considered a subscription | |
newSubscription = { dispose: () => value.cancel(), value }; | |
} else { | |
// TODO: should we complain about a leak? i.e. a subscription with no teardown? | |
newSubscription = {} | |
} | |
} else { | |
// nothing returned, no new subscription. | |
newSubscription = {} | |
} | |
newSubscription.key = newKey; | |
if (!currentSubscription) { | |
_cleanupOnDestroy(hostObject, () => { | |
let v = hostObject[currentSubscriptionKey]; | |
if (v && v.dispose) { | |
v.dispose(); | |
v.dispose = null; | |
} | |
}); | |
} | |
hostObject[currentSubscriptionKey] = newSubscription; | |
return newSubscription.value; | |
} | |
} | |
debugger; | |
super(getter, { dependentKeys, readOnly: true }); | |
} | |
setup(proto, propertyName) { | |
ComputedProperty.prototype.setup.apply(this, arguments); | |
debugger; | |
let dks = this._dependentKeys || []; | |
addListener(proto, "init", null, function() { | |
// get all dks to ensure observers are active (is this still necessary?) | |
this.get(propertyName); // kick off initial .get() | |
}); | |
// the observer keeps the underlying CP alive | |
addObserver(proto, propertyName, null, function() { | |
this.get(propertyName); | |
}); | |
} | |
} | |
export function subscription(...args) { | |
let subscriptionConstructor = args.pop(); | |
let dependentKeys = args; | |
return new SubscriptionManager(subscriptionConstructor, dependentKeys); | |
} | |
// const superSetup = ComputedProperty.prototype.setup; | |
// SubscriptionManagaer.prototype = Object.create(ComputedProperty.prototype); | |
// this is lifted from ember-concurrency; | |
// ember-lifeline does something like this too. | |
// TL;DR we need a better shared primitive | |
function _cleanupOnDestroy(owner, object, cleanupMethodName, ...args) { | |
// TODO: find a non-mutate-y, non-hacky way of doing this. | |
if (!owner.willDestroy) | |
{ | |
// we're running in non Ember object (possibly in a test mock) | |
return; | |
} | |
if (!owner.willDestroy.__ember_processes_destroyers__) { | |
let oldWillDestroy = owner.willDestroy; | |
let disposers = []; | |
owner.willDestroy = function() { | |
for (let i = 0, l = disposers.length; i < l; i ++) { | |
disposers[i](); | |
} | |
oldWillDestroy.apply(owner, arguments); | |
}; | |
owner.willDestroy.__ember_processes_destroyers__ = disposers; | |
} | |
owner.willDestroy.__ember_processes_destroyers__.push(() => { | |
object[cleanupMethodName](...args); | |
}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"version": "0.15.1", | |
"EmberENV": { | |
"FEATURES": {} | |
}, | |
"options": { | |
"use_pods": false, | |
"enable-testing": false | |
}, | |
"dependencies": { | |
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js", | |
"ember": "3.4.3", | |
"ember-template-compiler": "3.4.3", | |
"ember-testing": "3.4.3" | |
}, | |
"addons": { | |
"ember-concurrency": "0.8.22" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment