Maintenance Mode
Ember FSM was a lot of fun to develop 4 years ago when this all made a lot of sense to me, it's still used in some places and I will continue to maintain it to prevent apps from breaking. If you think the Ember community still needs a library like this with newer/better features please fork it and I will let people know where to go! Thanks for understanding
A wild (and current) traffic light demo appears!
import FSM from 'ember-fsm';
let trafficSignal = FSM.Machine.create({
events: {
cycle: {
transitions: [
{ initialized: 'red' },
{ red: 'green' },
{ green: 'amber' },
{ amber: 'red' }
]
},
powerDown: {
transition: { $all: 'off' }
}
}
});
trafficSignal.get('currentState');
// "initialized"
trafficSignal.send('cycle');
trafficSignal.get('currentState');
// "red"
trafficSignal.send('cycle');
trafficSignal.get('currentState')
// "green"
Install as an Ember Addon
ember install ember-fsm
Try really hard not to need it, if you need it, I'm sorry. -- @heycarsten
import FSM from 'ember-fsm';
let SleepyFSM = FSM.Machine.extend({
// Here is where you define your state machine's state-specific configuration.
// This section is optional.
states: {
// The default initial state is "initialized"
initialState: 'awake'
// If you'd like, you can choose to explicitly define the names of your
// states:
knownStates: ['sleeping', 'angry', 'awake', 'initialized', 'failed'],
// You can define global per-state callbacks, they will fire whenever the
// state will be entered, was entered, will be exited, or was exited.
sleeping: {
willEnter() { },
didEnter() { },
willExit() { },
didExit() { }
}
},
// Here's where you define your state machine's events, it is required.
events: {
sleep: {
// You can define global per-event callbacks. These will fire for any
// transition before or after this event.
before() { },
after() { },
// This is where the event's transitions are defined, it is also aliased
// to "transition". It can accept either a single object like one in the
// array below, or an array of transition definition objects:
transitions: [
{ awake: 'sleeping', doUnless: 'unableToSleep' },
{ awake: 'angry', doIf: 'unableToSleep' },
{ sleeping: '$same' }
]
},
// By default this error event is injected into your state machine for you,
// you can override it and provide your own transitions and callbacks if
// you'd like.
error: {
transition: { $all: 'failed' }
}
}
});
For the sake of less typing (and less chances of introducing failure) thefollowing macros can be used in transition definitions:
Macro | Description |
---|---|
$all |
Expands to all known states. |
$same |
Expands to the same state as the from state. transition: { sleeping: '$same' } |
$initial |
Expands to the initial state. |
You can specify that a transition be excluded or included in the event usingdoIf
or doUnless
. Consider SleepyFSM
above, if we set unableToSleep
totrue
then when we send in the sleep
event, it will transition to the stateangry
because the transition { awake: 'sleeping' }
will be excluded fromthe list.
doIf
and doUnless
are aliased to guard
and unless
respectively.
Given the SleepyFSM
example above, suppose we ran the following:
let fsm = SleepyFSM.create();
fsm.send('sleep');
Here is the series of transition events that will occurr and the correspondingcallbacks that will run and where they can be defined:
Current State | Is Active | Event | Runs callbacks |
---|---|---|---|
awake | false | beforeEvent |
before on events and transitions |
awake | true | _activateTransition_ |
internal |
awake | true | willExit |
willExit on states and transitions |
awake | true | willEnter |
willEnter on states and transitions |
sleeping | true | _setNewState_ |
internal |
sleeping | true | didExit |
didExit on states and transitions |
sleeping | true | didEnter |
didEnter on states and transitions |
sleeping | false | _deactivateTransition_ |
internal |
sleeping | false | afterEvent |
after on events and transitions |
Some of the event names above also have aliases:
Event | Aliases |
---|---|
beforeEvent |
before |
afterEvent |
after |
didEnter |
enter , action |
didExit |
exit |
If callbacks return a promise, the next callback in the chain will not fireuntil the promise is resolved. The return value of callbacks is stored in thetransition's resolutions
object. Likewise, rejections are stored in therejections
object of the transition.
ember-fsm
doesn't provide true sub-state support, but you can namespace yourstates. For example, suppose a portion of your state workflow is related insome way; you can prefix those states with a namespace:
When you define states like this, Ember.FSM automatically generates thefollowing boolean accessor properties for you:
When it comes to using ember-fsm
in your application, you'll almost alwayswant to use FSM.Stateful
over sub-classing FSM.Machine
. This wayyou can formalize a state workflow around something like file uploads where youmight have to incorporate three different proceesses into on user experience.
Note: States and events are renamed in the mixin to fsmStates
and fsmEvents
respectively, to avoid conflict with core Ember properties.
Building these sorts of workflows implicitly as-you-code-along can be a recipiefor massive sadness. So why be sad? Formalize that workflow! Here's an exampleof how adding ember-fsm
to a controller can remove a lot of thetedious parts of workflow managment:
import Ember from 'ember';
import FSM from 'ember-fsm';
// controllers/upload.js
export default Ember.Controller.extend(FSM.Stateful, {
needs: 'notifier',
actions: {
uploadFile(file) {
this.set('file', file);
this.sendStateEvent('addFile');
}
},
fsmStates: {
initialState: 'nofile'
},
fsmEvents: {
addFile: {
transitions: {
from: ['nofile', 'failed'],
to: 'ready',
before: 'checkFile',
}
},
startUpload: {
transitions: {
from: 'ready',
to: 'uploading',
before: 'getUploadURL',
didEnter: 'performUpload',
after: 'finishedUpload'
}
},
finishUpload: {
transition: { uploading: 'nofile', didEnter: 'reset' }
}
},
reset() {
this.set('file', null);
},
checkFile() {
let file = this.get('file');
if (file.size > 0) {
return;
} else {
this.get('controllers.notifier').warn('file must have content');
FSM.reject(); // A helper for throwing an error
}
},
getUploadURL() {
let fileName = this.get('file.name');
let xhr = Ember.$.ajax('/api/signed_uploads', {
type: 'put',
data: { file: { name: fileName } }
});
xhr.then((payload) => {
Ember.run(() => {
this.set('uploadToURL', payload.signed_upload.url);
});
});
return xhr; // Causes transition to block until promise is settled
},
performUpload() {
return Ember.$.ajax(this.get('uploadToURL'), {
type: 'put',
data: this.get('file')
});
},
finishedUpload() {
this.get('controllers.notifier').success('Upload complete');
this.sendStateEvent('finishUpload');
}
});
ember test
– Runs the test suite on the current Ember versionember test --server
– Runs the test suite in "watch mode"ember try:each
– Runs the test suite against multiple Ember versionsember serve
Ember检查器是一个浏览器插件,用于调试Ember应用程序。 灰烬检查员包括以下主题 - S.No. 灰烬检查员方式和描述 1 安装Inspector 您可以安装Ember检查器来调试您的应用程序。 2 Object Inspector Ember检查器允许与Ember对象进行交互。 3 The View Tree 视图树提供应用程序的当前状态。 4 检查路由,数据选项卡和库信息 您可以看到检查
英文原文: http://emberjs.com/guides/getting-ember/index/ Ember构建 Ember的发布管理团队针对Ember和Ember Data维护了不同的发布方法。 频道 最新的Ember和Ember Data的 Release,Beta 和 Canary 构建可以在这里找到。每一个频道都提供了一个开发版、最小化版和生产版。更多关于不同频道的信息可以查看博客
ember-emojione ember-emojione is your emoji solution for Ember, based on the EmojiOne project. EmojiOne version 2 is used, which is free to use for everyone (CC BY-SA 4.0), you're only required to giv
Ember 3D Ember 3D is an Ember addon for using Three.js - an easy to use, lightweight, javascript 3D library. It is designed to: Prescribe a solid file structure to Three.js code using ES6 modules. Ena
Ember Table An addon to support large data set and a number of features around table. Ember Table canhandle over 100,000 rows without any rendering or performance issues. Ember Table 3.x supports: Emb
vscode-ember This is the VSCode extension to use the Ember Language Server. Features All features currently only work in Ember-CLI apps that use classic structure and are a rough first draft with a lo