# 实战篇 06:消息通知设计
本节参考代码: react-boilerplate-pro
在传统的企业管理系统中一个经常被忽略掉的细节就是对于用户操作的反馈。一方面是因为复杂的业务流程边界条件太多,每一个分支都给予适当的反馈是一件非常烦琐的事情。另一方面往往是因为系统架构设计得不够灵活,只是显示一个操作成功或失败的通知就要写大量重复的逻辑代码,导致专注于业务流程的开发者不愿意花时间去处理操作反馈这一“可有可无”的需求。
在操作反馈通知(Notification)之外,完善的企业管理系统还需要一个全局的消息系统以方便系统管理员向某些或全部成员发送系统消息(Notice),即应用页眉中的通知栏,如 ant-design-pro 中的例子。

# 全局通知栏与应用初始化
与前端主导的通知系统不同,系统消息更依赖后端的实现。这里我们假设后端提供了获取当前用户未读消息的接口 /notices,创建相应的 redux action 为:
const getNotices = () => (
createAsyncAction('APP_GET_NOTICES', () => (
api.get('/notices')
))
);
@前端进阶之旅: 代码已经复制到剪贴板
# 应用数据初始化
在实现系统消息之前,我们首先要解决应用数据初始化的问题。以系统消息为例,用户在登录系统后点击应用页眉中的通知栏就应当立刻可以看到当前的未读消息。但获取用户未读消息是一个异步的过程,这里的异步请求应该在什么时候发出呢?
最简单的解决方案当然是在用户点击通知栏时发出,但这样做的弊端是用户在阅读消息前需要等待时间,没有充分利用到用户登录系统后但未点击通知栏这段空闲时间,而且如果用户频繁点击通知栏的话还会导致大量的冗余异步请求被发送至后端。
另一个解决方案就是在用户成功登录后发送请求去取得最新的未读消息:
const login = (username, password) => (
createAsyncAction('APP_LOGIN', () => (
api.post('/login', {
username,
password,
})
))
);
const loginUser = (username, password) => {
const action = login(username, password);
return dispatch => (
action(dispatch)
.then(((callbackAction) => {
if (callbackAction.type === 'APP_LOGIN_SUCCESS') {
return getNotices()(dispatch);
}
return null;
}))
);
};
@前端进阶之旅: 代码已经复制到剪贴板
但这样做会有一个例外就是因为系统会记录用户的登录状态,在鉴权过期前用户刷新页面是不需要重新登录的。这时我们就需要在系统初始化时,判断如果用户已经登录就发送获取系统消息的请求。
const initClient = (dispatch) => {
const commonActions = [
dispatch(appAction.getLocale()),
];
const isLogin = !isNil(Cookie.get('user'));
if (isLogin) {
commonActions.push(dispatch(appAction.getNotices()));
}
return commonActions;
};
@前端进阶之旅:
