一個對象有狀態變化
每次狀態變化都會觸發一個邏輯
不能老是用 if...else 來控制javascript
示例:交通訊號燈的不一樣顏色變化css
class State { constructor(color) { this.color = color; } handle(context) { console.log(`turn to ${this.color} light`); context.setState(this); } } class Context { constructor() { this.state = null; } setState(state) { this.state = state; } getState() { return this.state; } } // 測試代碼 let context = new Context(); let greed = new State("greed"); let yellow = new State("yellow"); let red = new State("red"); // 綠燈亮了 greed.handle(context); console.log(context.getState()); // 黃燈亮了 yellow.handle(context); console.log(context.getState()); // 紅燈亮了 red.handle(context); console.log(context.getState());
npm install javascript-state-machine --save
有限狀態機的收藏與取消html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Document</title> </head> <body> <p>有限狀態機</p> <button id="btn"></button> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script src="./03-javascript-state-machine.js"></script> <script> // 狀態機模型 var fsm = new StateMachine({ init: "收藏", // 初始狀態,待收藏 transitions: [ { name: "doStore", from: "收藏", to: "取消收藏" }, { name: "deleteStore", from: "取消收藏", to: "收藏" } ], methods: { // 執行收藏 onDoStore: function() { alert("收藏成功"); updateText(); }, // 取消收藏 onDeleteStore: function() { alert("已取消收藏"); updateText(); } } }); var $btn = $("#btn"); // 點擊事件 $btn.click(function() { if (fsm.is("收藏")) { fsm.doStore(1); } else { fsm.deleteStore(); } }); // 更新文案 function updateText() { $btn.text(fsm.state); } // 初始化文案 updateText(); </script> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Document</title> </head> <body> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script src="./03-javascript-state-machine.js"></script> <script> // 模型 var fsm = new StateMachine({ init: "pending", transitions: [ { name: "resolve", from: "pending", to: "fullfilled" }, { name: "reject", from: "pending", to: "rejected" } ], methods: { // 成功 onResolve: function(state, data) { // 參數:state - 當前狀態示例; data - fsm.resolve(xxx) 執行時傳遞過來的參數 data.successList.forEach(fn => fn()); }, // 失敗 onReject: function(state, data) { // 參數:state - 當前狀態示例; data - fsm.reject(xxx) 執行時傳遞過來的參數 data.failList.forEach(fn => fn()); } } }); // 定義 Promise class MyPromise { constructor(fn) { this.successList = []; this.failList = []; fn( () => { // resolve 函數 fsm.resolve(this); }, () => { // reject 函數 fsm.reject(this); } ); } then(successFn, failFn) { this.successList.push(successFn); this.failList.push(failFn); } } // 測試代碼 function loadImg(src) { const promise = new MyPromise(function(resolve, reject) { var img = document.createElement("img"); img.onload = function() { resolve(img); }; img.onerror = function() { reject(); }; img.src = src; }); return promise; } var src = "https://blog-static.cnblogs.com/files/ygjzs/images.gif"; var result = loadImg(src); console.log(result); result.then( function(img) { console.log("success 1"); }, function() { console.log("failed 1"); } ); result.then( function(img) { console.log("success 2"); }, function() { console.log("failed 2"); } ); </script> </body> </html>