在前兩篇文章
【帶并發(fā)限制的異步調(diào)度器Ⅰ】原始Demo
【帶并發(fā)限制的異步調(diào)度器Ⅱ】點餐排隊系統(tǒng)Demo
的基礎(chǔ)上沼头,這次加入了圖形化界面国夜,這樣就升級成一個完整的項目。我把這三篇文章總結(jié)為以下三種遞進的階段:
①單通道的任務(wù)調(diào)度器
②多通道的任務(wù)調(diào)度器准谚,無頁面的應(yīng)用場景演示Demo阿纤,并增加了通道數(shù)及任務(wù)運行數(shù)的初始化配置
③多通道的任務(wù)調(diào)度器甚负,有頁面的應(yīng)用場景操作纬傲,可配置初始化信息并持久化保存襟衰,可查看某一任務(wù)的運行情況贴铜,可實時添加及移除任務(wù)
第三階段的技術(shù)總結(jié)如下:
- React組件圖形化界面,形成最原始的可視化頁面
- Egg.js企業(yè)級Node.js框架瀑晒,提供接口請求以及安全防護
- Mongoose數(shù)據(jù)庫存儲绍坝,持久化配置信息
- React-redux提供組件間交互的狀態(tài)管理,store機制給所有組件(隔層組件以及不同頁面組件)提供全局數(shù)據(jù)
- Ant Design模態(tài)框提供便于交互的組件服務(wù)
第三階段的功能點總結(jié)如下:
- 在“初始化”界面添加配置桌子信息苔悦,可移除添加的信息轩褐,可編輯添加的信息(添加相同人數(shù)的桌子信息即可覆蓋原信息),可點擊“完成配置”持久化配置數(shù)據(jù)玖详,以供下次啟動試用把介,可立即切換到“點餐排隊”使用配置信息
- 進入系統(tǒng)時,系統(tǒng)會自動請求配置數(shù)據(jù)接口初始化操作頁面需要用到的全局數(shù)據(jù)store(“點餐排隊”和“初始化”使用的是store里的同一個數(shù)據(jù)源)
-
點擊初始化后蟋座,會出現(xiàn)后續(xù)操作按鈕拗踢,點擊“查看桌子使用信息”,會出現(xiàn)桌子的使用信息情況
操作按鈕
-
點擊“用餐入座”向臀,相應(yīng)的顧客就會在N人桌里占一個位子巢墅,如果有空閑桌,可以直接用餐(若按原始Demo的說法,就是執(zhí)行任務(wù)隊列有空缺君纫,任務(wù)直接進入執(zhí)行任務(wù)隊列運行驯遇,若已滿,則會進入待執(zhí)行任務(wù)隊列)蓄髓,若沒有叉庐,則會拿到一個排隊編號等待入座
添加用餐信息
- 當拿到編號時,可點擊“查看某桌排隊情況”会喝,輸入相應(yīng)編號來查看此編號目前所處的情況陡叠,具體情況如下:
- 無此桌點餐信息
- 正在用餐
- 排隊情況
- 排隊情況
- 當某桌用餐結(jié)束時,可點擊“結(jié)束用餐”好乐,輸入桌子編號匾竿,把執(zhí)行任務(wù)從正在用餐隊列里移除
以上就是此系統(tǒng)的全部功能,完整項目放在github上蔚万,如有需要請自取岭妖。
總結(jié)下開發(fā)此系統(tǒng)遇到的問題:
- 服務(wù)端無法接受 post 請求,并且請求接口報錯
403 :message: 'invalid csrf token'
原因:Egg框架內(nèi)置中間件安全防護反璃,默認開啟防止 XSS 攻擊 和 CSRF 攻擊昵慌,所以前端請求post
接口時需要在header請求頭里添加csrfToken
,讓Egg幫忙驗證淮蜈,具體配置如下:
server端:
//config.default.js
//csrf配置
exports.security= {
csrf : {
headerName: 'x-csrf-token', // 自定義請求頭
}
}
client端:
'use strict'
import api from './api';
// 封裝獲取 cookie 的方法
function getCookie(name){
var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
if(arr=document.cookie.match(reg))
return unescape(arr[2]);
else
return null;
}
function saveSetting(deskData, successCB, failCB) {
return $.ajax({
url: api.COMPANY + '/setting',
method: 'POST',
contentType: 'application/json',
headers:{
// 前后端不分離的情況加每次打開客戶端斋攀,egg會直接在客戶端的 Cookie 中寫入密鑰 ,
//密鑰的 Key 就是 'scrfToken' 這個字段梧田,所以直接獲取就好了
'x-csrf-token': getCookie("csrfToken"),
},
data: JSON.stringify({ data:deskData })
}).then(successCB, failCB);
}
- 開發(fā)前端的操作頁面時淳蔼,對React-redux的store使用不當,導(dǎo)致不同頁面組件獲取store中的全局數(shù)據(jù)出現(xiàn)問題裁眯。
具體情況:當把頁面組件從UI組件變?yōu)槿萜鹘M件(使用connect處理)時鹉梨,未能成功獲取到store數(shù)據(jù),但實際是錯誤理解了React-redux和redux獲取全局數(shù)據(jù)store的方式穿稳。
解決:React-redux子組件獲取store的方式是在mapStateToProps方法中處理的存皂,而redux是通過this.context.store
來獲取,以下是React-redux獲取store的項目代碼:
/app/view/container/DinnerPane.js
import { connect } from 'react-redux';
import dinnerPane from '../component/dinnerPane/dinnerPane';
function mapStateToProps(state) {
return {
deskData: state.deskData||{}
};
}
function mapDispatchToProps(dispatch) {
return {};
}
export default connect(mapStateToProps, mapDispatchToProps)(dinnerPane);
初始化store是在dinnerPane的上層容器Content里處理的逢艘,先請求配置數(shù)據(jù)get
接口旦袋,然后dispatch
initDeskDataAction到store里更新數(shù)據(jù):
/app/view/container/content/Content.js
import { connect } from 'react-redux';
import Content from '../../component/Content/Content';
import { getSetting } from '../../utils/WebAPIUtils';
import { initDeskDataAction } from '../../action/initDataActionCreator'
function mapStateToProps(state) {
return {
deskData: state.deskData
};
}
function mapDispatchToProps(dispatch) {
return {
initDeskDataRequest: function (companyId, callback) {
return getSetting(companyId, function (result) {
callback(null, result);
}, function (err){
callback(err);
});
},
initDeskData: function(deskData){
dispatch(initDeskDataAction(deskData));
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Content);