Skip to content

Instantly share code, notes, and snippets.

@givanse
Last active January 24, 2020 15:56
Show Gist options
  • Save givanse/57eed26408aa0aeea2f9f4b3095a0a27 to your computer and use it in GitHub Desktop.
Save givanse/57eed26408aa0aeea2f9f4b3095a0a27 to your computer and use it in GitHub Desktop.
Ember runloop demonstration with a computed property and an observer
import Ember from 'ember';
export default Ember.Component.extend({
firstName: null,
lastName: null,
logs: [],
_log: function(log) {
let logs = this.get('logs');
logs.pushObject(log);
},
/**
*
* Computeds use the Ember runloop.
*
*/
fullName: Ember.computed('firstName', 'lastName', function() {
let firstName = this.get('firstName');
let lastName = this.get('lastName');
let fullName = firstName + ' ' + lastName;
this._log('fullName computed> ' + fullName);
return fullName;
}),
fullNameAgain: null,
/**
* Observers are synchornous, they don't use the Ember runloop.
*/
_setfullNameAgain: Ember.observer('firstName', 'lastName', function() {
let fullNameAgain = `${this.get('firstName')} ${this.get('lastName')}`;
this._log('fullName observer> ' + fullNameAgain);
this.set('fullNameAgain', fullNameAgain);
}),
consecutiveUpdates: function() {
this.set('logs', []);
this._log('console cleared');
// https://guides.emberjs.com/v2.7.0/applications/run-loop/#toc_why-is-the-run-loop-useful
this.set('firstName', 'Yehuda');
this.set('lastName', 'Katz');
this.set('firstName', 'Tom');
this.set('lastName', 'Huda');
},
actions: {
update: function() {
this.consecutiveUpdates();
}
}
});
body {
margin: 12px 16px;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12pt;
}
.flex {
display: flex;
}
.col {
border: 1px solid gray;
border-radius: 8px;
padding: 16px;
margin: 2px;
}
.console {
background-color: #dedede;
min-height: 200px;
border-radius: 4px;
padding: 4px;
}
<h1>Ember runloop</h1>
<h3>comparing computeds and observers</h3>
{{foo-bar}}
First name:
{{input value=firstName}}
<br>
Last name:
{{input value=lastName}}
<br>
<br>
<div class="flex">
<div class="col">
Inputs
<br>
<br>
first name: {{firstName}}
<br>
last name: {{lastName}}
</div>
<div class="col">
Full name
<br>
<br>
computed: {{fullName}}
<br>
<!-- empty on the first render because observers don't fire on initialization -->
&nbsp;&nbsp;observer: {{fullNameAgain}}
</div>
</div>
<br>
<button {{action "update"}}>
set names two consecutive times
</button>
<pre>
this.set('firstName', 'Yehuda');
this.set('lastName', 'Katz');
this.set('firstName', 'Tom');
this.set('lastName', 'Huda');
</pre>
<p>
Notice how the end result is the same, but the console tells a different story.
</p>
<p>
For the observer we see invalid intermediate values that could become the source of subtle bugs.
</p>
<div class="console">
Console
<br>
<br>
{{#each logs as |str|}}
{{str}}
<br>
{{/each}}
</div>
{
"version": "0.10.4",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js",
"ember": "2.7.0",
"ember-data": "2.7.0",
"ember-template-compiler": "2.7.0"
},
"addons": {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment