【问题标题】:How to use RxJS in Vuex module如何在 Vuex 模块中使用 RxJS
【发布时间】: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() 中,尝试将返回值更改为PromisetoPromise

标签: typescript vue.js rxjs axios vuex-modules


【解决方案1】:

authRequest 正在返回 Subscription 但要使用 .then onSubmit 逻辑在这里需要 Promise 类型。您可能想在authRequest 中使用.tap/.do 后跟.toPromise

【讨论】:

  • Franco,还有其他可以代替 .then 的吗?
【解决方案2】:

是的,您在操作中返回订阅,而您不想这样做。在您的操作中将 .subscribe 替换为 .pipe(shareReplay()) 。 Observable 实现了 PromiseLike,所以你可能会很好。如果这仍然不起作用,则必须在操作中的 return 语句末尾调用 .toPromise() 。一个 vuex-rxjs 库将是一件美好的事情,我希望我有时间去做。希望其他人很快就会这样做:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-28
    • 2023-04-08
    • 2021-02-26
    • 2021-06-05
    • 2021-01-27
    • 2020-02-13
    • 2019-05-23
    • 2018-05-06
    相关资源
    最近更新 更多