如何先根据后端响应初始化Vue应用?
How to initialize the Vue app depending on back-end response first?
我希望某些代码在应用程序中的任何其他内容之前成为 运行,该代码将向后端发送请求,然后更新商店。
我需要先执行那部分,因为路由守卫依赖于它,如何实现?
代码示例
正在获取用户信息和设置
async init() {
await AuthService.initCSRF();
await AuthService.getUser().then((res) => {
if (res.data && res.data.user) {
this.loginLocally(res.data.user);
} else {
this.logoutLocally();
}
});
}
Auth guard
export function isLoggedIn(to, from, next) {
console.log('Checked', store.state.auth.isLoggedIn);
if (store.state.auth.isLoggedIn) {
next();
return;
}
next({ name: 'login' })
}
可以在调用 .mount(...)
之前等待初始化承诺。问题是vue router启动separately from the application不会这样延迟
如果是依赖初始化过程的路由器,延迟路由器启动的一种方法是等待路由器钩子中的承诺先于其他承诺被触发:
const initPromise = init();
...
router.beforeEach(async (to, from, next) => {
await initPromise;
next();
});
在我的旧项目中,我做了这样的事情。希望你有所了解。
app.js
import App from './components/App.vue'
store.dispatch('auth/attempt', sessionStorage.getItem('token')).then(() =>{
new Vue({
el: '#app',
router,
store,
render: h => h(App),
});
});
这里我在呈现应用程序之前验证保存在本地存储中的令牌。
我的 Vuex 动作是这样的
async signIn({dispatch}, credentials) {
let response = await axios.post("auth/signin", credentials);
await dispatch('attempt', response.data.token)
},
async attempt({commit, state}, token) {
if (token) {
await commit('SET_TOKEN', token);
}
if (!state.token) {
return;
}
try {
let response = await axios.get('auth/me');
commit('SET_USER', response.data)
} catch (e) {
commit('SET_TOKEN', null);
commit('SET_USER', null);
}
},
async signOut({commit}) {
axios.post('auth/signout').then(() => {
commit('SET_TOKEN', null);
commit('SET_USER', null);
});
}
我正在使用订阅者来监听突变并在请求中添加或删除令牌headers
import store from '../store'
store.subscribe((mutation) => {
if (mutation.type === 'auth/SET_TOKEN') {
if (mutation.payload) {
axios.defaults.headers.common['Authorization'] = `Bearer ${mutation.payload}`;
sessionStorage.setItem('token', mutation.payload);
} else {
axios.defaults.headers.common['Authorization'] = null;
sessionStorage.removeItem('token');
}
}
});
最后一个用于句柄令牌过期的 axios 拦截器。
import router from '../plugins/router'
import store from '../store'
import axios from "axios";
axios.interceptors.response.use((response) => {
return response;
}, (error) => {
if (error.response.status) {
if (error.response.status === 401) {
if (router.currentRoute.name !== 'landing') {
store.dispatch('auth/clearToken').then(() => {
router.replace({
name: 'landing'
});
}).finally(() => {
swal.fire(
'Your Session is Expired',
'Please sign in again!',
'error'
)
});
}
}
}
return Promise.reject(error);
});
我希望某些代码在应用程序中的任何其他内容之前成为 运行,该代码将向后端发送请求,然后更新商店。 我需要先执行那部分,因为路由守卫依赖于它,如何实现?
代码示例
正在获取用户信息和设置
async init() {
await AuthService.initCSRF();
await AuthService.getUser().then((res) => {
if (res.data && res.data.user) {
this.loginLocally(res.data.user);
} else {
this.logoutLocally();
}
});
}
Auth guard
export function isLoggedIn(to, from, next) {
console.log('Checked', store.state.auth.isLoggedIn);
if (store.state.auth.isLoggedIn) {
next();
return;
}
next({ name: 'login' })
}
可以在调用 .mount(...)
之前等待初始化承诺。问题是vue router启动separately from the application不会这样延迟
如果是依赖初始化过程的路由器,延迟路由器启动的一种方法是等待路由器钩子中的承诺先于其他承诺被触发:
const initPromise = init();
...
router.beforeEach(async (to, from, next) => {
await initPromise;
next();
});
在我的旧项目中,我做了这样的事情。希望你有所了解。
app.js
import App from './components/App.vue'
store.dispatch('auth/attempt', sessionStorage.getItem('token')).then(() =>{
new Vue({
el: '#app',
router,
store,
render: h => h(App),
});
});
这里我在呈现应用程序之前验证保存在本地存储中的令牌。
我的 Vuex 动作是这样的
async signIn({dispatch}, credentials) {
let response = await axios.post("auth/signin", credentials);
await dispatch('attempt', response.data.token)
},
async attempt({commit, state}, token) {
if (token) {
await commit('SET_TOKEN', token);
}
if (!state.token) {
return;
}
try {
let response = await axios.get('auth/me');
commit('SET_USER', response.data)
} catch (e) {
commit('SET_TOKEN', null);
commit('SET_USER', null);
}
},
async signOut({commit}) {
axios.post('auth/signout').then(() => {
commit('SET_TOKEN', null);
commit('SET_USER', null);
});
}
我正在使用订阅者来监听突变并在请求中添加或删除令牌headers
import store from '../store'
store.subscribe((mutation) => {
if (mutation.type === 'auth/SET_TOKEN') {
if (mutation.payload) {
axios.defaults.headers.common['Authorization'] = `Bearer ${mutation.payload}`;
sessionStorage.setItem('token', mutation.payload);
} else {
axios.defaults.headers.common['Authorization'] = null;
sessionStorage.removeItem('token');
}
}
});
最后一个用于句柄令牌过期的 axios 拦截器。
import router from '../plugins/router'
import store from '../store'
import axios from "axios";
axios.interceptors.response.use((response) => {
return response;
}, (error) => {
if (error.response.status) {
if (error.response.status === 401) {
if (router.currentRoute.name !== 'landing') {
store.dispatch('auth/clearToken').then(() => {
router.replace({
name: 'landing'
});
}).finally(() => {
swal.fire(
'Your Session is Expired',
'Please sign in again!',
'error'
)
});
}
}
}
return Promise.reject(error);
});