如何在 Vuex 模块中使用 RxJS
Posted
技术标签:
【中文标题】如何在 Vuex 模块中使用 RxJS【英文标题】:How to use RxJS in Vuex module 【发布时间】:2019-12-23 16:33:31 【问题描述】:我创建了一个供 Vuex 模块使用的身份验证服务使用的 API 服务。在我的登录组件中,我使用 Vuex 模块与 API 进行通信,但调用不等待 API 响应。
API 服务:
class ApiService
protected readonly api = 'https://xxx.yzz:44310/api'
private static instance: ApiService
private headers =
'Content-Type': 'application/json'
constructor()
this.init()
private init()
Vue.use(VueAxios, axios)
Vue.axios.defaults.baseURL = this.api
public static get Instance()
return this.instance || (this.instance = new this())
private handleError(error: any)
const applicationError = error.headers['Application-Error']
return Observable.throw(modelStateErrors || 'Server error')
get(path: string, params: URLSearchParams = new URLSearchParams()): Observable<any>
return from(axios.get(`$path`, params )).pipe(catchError(this.handleError))
put(path: string, body: Object = ): Observable<any>
return from(axios.put(`$path`, JSON.stringify(body))).pipe(catchError(this.handleError))
post(path: string, body: Object = ): Observable<any>
return from(
axios.post(`$path`, JSON.stringify(body),
headers: this.headers
)
).pipe(catchError(this.handleError))
export const apiService = ApiService.Instance
授权服务:
class AuthService
private static instance: AuthService
private constructor()
public static get Instance()
return this.instance || (this.instance = new this())
public login(credentials: Credentials): Observable<any>
return apiService.post('/auth/login', credentials).pipe(map(result => result.data))
export const authService = AuthService.Instance
带有授权方式的Vuex模块:
import Module, VuexModule, Mutation, Action from 'vuex-module-decorators'
import Credentials from '@/core/models/credentials.interface'
import authService from '@/core/services/auth.service'
import Usuario from '@/core/models/usuario.interface'
@Module
export default class Auth extends VuexModule
count = 0
usuario: Usuario | null = null
isAuthenticated: boolean = false
@Mutation
setUsuario(usuario: Usuario)
this.usuario = usuario
this.isAuthenticated = true
@Action()
public authRequest(credentials: Credentials)
return authService.login(credentials).subscribe(
(usuario: Usuario) =>
this.context.commit('setUsuario', usuario)
,
(errors: any) =>
console.log('errors', JSON.stringify(errors))
)
在我的登录组件中,我使用 Vuex 模块如下:
onSubmit()
(this.$refs.userCredentials as any).validate((valid: boolean) =>
if (valid)
this.$store
.dispatch('authRequest', this.userCredentials)
.then(() =>
this.$router.push('/');
)
.catch((err) =>
console.error(err);
);
else
console.log('error submit!!');
return false;
);
我期望的结果是,当我按下登录按钮时,代码会一直等到 API 响应,然后根据结果执行后续步骤。
【问题讨论】:
Vuex 操作通常需要文字或Promise
作为返回。在Auth.authRequest()
中,尝试将返回值更改为Promise
和toPromise
。
【参考方案1】:
authRequest
正在返回 Subscription
但要使用 .then
onSubmit
逻辑在这里需要 Promise
类型。您可能想在authRequest
中使用.tap
/.do
后跟.toPromise
【讨论】:
Franco,还有其他可以代替 .then 的吗?【参考方案2】:是的,您在操作中返回订阅,而您不想这样做。在您的操作中将 .subscribe 替换为 .pipe(shareReplay()) 。 Observable 实现了 PromiseLike,所以你可能会很好。如果这仍然不起作用,则必须在操作中的 return 语句末尾调用 .toPromise() 。一个 vuex-rxjs 库将是一件美好的事情,我希望我有时间去做。希望其他人很快就会这样做:)
【讨论】:
以上是关于如何在 Vuex 模块中使用 RxJS的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Vuex 模块 Actions 中使用 vue-router?
如何在 Vuex 4 和 TypeScript 中使用其他存储模块 getter/actions/mutations