实际上参考的就是 stackoverflow 中的这个回答,momentjs set the base time from the server,文章认为利用服务器回传的时间和当前浏览器中的时间做差,记录下时间差值,然后在每次初始化 moment 对象的时候加上差值,再把对象返回即可。程序就是对这个的实现。
由于需要在全局引用该方法,所以直接利用 vuex 来写就够了。
首先定义一个模块timer,用于和项目中其他的相区分
import auth from './auth.js';
import timer from './timer.js';
export default new Vuex.Store({
modules: {
auth,
timer
},
state: {},
mutations: {},
actions: {}
});
在模块中实现获取服务器时间,记录插值,返回与服务器时间同步的moment对象。
// timer.js
export default {
state: {
// 服务器和本地的时间相差的秒数
delaySeconds: 0
},
mutations: {
SET_DELAY_SECOND (state, delaySeconds) {
state.delaySeconds = delaySeconds;
}
},
actions: {
async getServerTime ({ commit }) {
const aaa = await getServerTime();
const serverTime = // 处理接口返回的时间为moment对象
const browserTime = moment();
// 这里可以设置millionSeconds以获取更加精准的时间
const delaySecond = serverTime.diff(browserTime, 'seconds');
commit('SET_DELAY_SECOND', delaySecond);
}
},
getters: {
// 初始化moment对象的时候加上差值,再把对象返回即可
serverTime: state => {
const time = moment();
time.add(state.timer.delaySecond, 'seconds');
return moment(time);
}
}
}
之后在系统的登录接口中调用该 action 即可。由于登录和获取服务器时间并不在一个 module 中,在跨模块调用 action 的时候还需要传入{root: true}
的对象,才能够正确找到 actions。
// auth.js
export default {
actions: {
Login ({ dispatch }) {
... // some login methods
dispatch('getServerTime', null, { root: true });
}
}
}