必须刷新页面才能从api获取数据

科林·拉格纳洛克(ColinRagnarök)

我有一个正在工作的身份验证。流。只有一个奇怪的错误。当我以第一个用户身份登录时,我首先必须刷新页面才能在我的视图中获取数据。当我用该用户注销并下一个用户登录时,我的视图中仍然有user1的数据。如果我再次使用user2注销并使用user3登录,则我的视图中将包含user2的数据。因此,似乎总是落后一步。我试图通过销毁订阅来解决此问题,但这并不能解决问题。同样,当我认为该错误开始时,我必须刷新页面以获取我的第一个用户数据,销毁订阅也不能成为错误解决方案。

这是我的代码:

auth.service:我在其中发布用户凭据,交还令牌,并存储它和user_id以便在视图中获取经过身份验证的用户数据。

import { Storage } from '@ionic/storage';
import { JwtHelperService } from '@auth0/angular-jwt';


export const TOKEN_KEY = 'access_token';
export const USERNAME_KEY = 'username_key';
export const USER_ID = 'user_id';
...
user = null;
refreshToken = null;
authenticationState = new BehaviorSubject(false);

  constructor(private storage: Storage, private helper: JwtHelperService) {
      this.checkToken();
   }

   checkToken() {
       this.storage.get(TOKEN_KEY).then(access => {
           if (access) {
               this.user = this.helper.decodeToken(access);
               this.authenticationState.next(true);
           }
       });
   }

   apilogin(username: string, password: string) {
    return this.http.post<any>(`${this.url}`, { username, password })
    .pipe(
        tap(res => {
            this.storage.set(TOKEN_KEY, res['access']);
            this.storage.set(USERNAME_KEY, username);
            this.storage.set(USER_ID, this.user['user_id']);
            this.user = this.helper.decodeToken(res['access']);
            console.log('my user: ', this.user);
            this.authenticationState.next(true);
        }));
}

apilogout() {
    this.storage.remove(USER_ID);
    this.storage.remove(USERNAME_KEY);
    this.storage.remove(TOKEN_KEY).then(() => {
    this.authenticationState.next(false);
   });
}

page.ts:在这里,我得到了在视图中显示的数据。(用户服务只检索一个用户。最后,我销毁了订阅)

import { Storage } from '@ionic/storage';
import { USER_ID } from 'src/app/services/auth.service';
import { SubscriptionLike } from 'rxjs';

  information = null;
  id: number;
  key: string;
  subscription: SubscriptionLike;

  constructor(private storage: Storage,  private activatedRoute: ActivatedRoute,
              private userService: UserService, private authService: AuthService) { }

  ngOnInit() {
    // How to get just the authenticated api?
      if (this.authService.authenticationState) {
      console.log(this.storage);
      this.storage.get(USER_ID).then(val => {
        this.id = val;
        this.subscription = this.userService.getUserDetails(this.id).subscribe(result => {
          this.information = result;
          console.log(this.information);
        });
      });
    }

  }

ngOnDestroy() {
this.subscription.unsubscribe();
this.information = null;
}

login.ts(处理我到主页的路由)

 // get return url from route parameters or default to '/'
    this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
...

apiSubmit() {
  console.log('Hello World');
  this.submitted = true;

  // if form is invalid => stop
  if (this.loginForm.invalid) {
      return;
  }
  this.isLoading = true;
  this.loadingEl.present();
  this.authService.apilogin(
  this.f.username,
  this.f.password)
      .pipe(tap(x => this.loadingEl.dismiss()),
      )
      .subscribe(
        data => {
          console.log('0');
          this.router.navigate([this.returnUrl]);
        },
        error => {
          console.log('1');
          this.loadingEl.dismiss();
          this.error = error;
          this.isLoading = false;
        }
      );
}

认证卫士

export class AuthGuard implements CanActivate {
  constructor(
      private router: Router,
      private authService: AuthService
  ) { }


  canActivate(): boolean {
    return this.authService.isAuthenticated();
  }
} 
AJT82

相反,if (this.authService.authenticationState) {您实际上应该订阅此可观察的内容。我们还需要记住,离子的设置或获取Storage实际上是异步的。我们需要等待动作已执行,然后再执行其他操作。我也建议不要调用next您的可观察对象,而只需调用checkToken()可以进行检查的对象,然后调用nextBehaviorSubject。

这应该工作:

服务:

import { BehaviorSubject, of, forkJoin } from 'rxjs';
import { tap, switchMap, map } from 'rxjs/operators';

// ...

private authenticationState = new BehaviorSubject(false);
public authenticationState$ = this.authenticationState.asObservable();

checkToken() {
  this.storage.get(TOKEN_KEY).then(access => {
    if (access) {
      this.authenticationState.next(true);
    } else {
      this.authenticationState.next(false);
    }
  });
}

apilogin(username: string, password: string) {
  return this.http.post<any>(`${this.url}`, { username, password }).pipe(
    // switch to inner observable
    switchMap((data: any) => {
      // run all in paralell
      return forkJoin(
        this.storage.set(TOKEN_KEY, 'access'),
        this.storage.set(USERNAME_KEY, 'username'),
        this.storage.set(USER_ID, 'id'),
      )
    }),
    // now we know for sure storage values have been set,
    // therefore call checkToken()
    tap(() => this.checkToken()),
  )
}

// seems you are not currently subscribing to this function in the
// component, so I guess you can subscribe here, but I'd subscribe in comp
apilogout() {
  forkJoin(
    this.storage.remove(USER_ID),
    this.storage.remove(REFRESH_TOKEN_KEY),
    this.storage.remove(USERNAME_KEY),
    this.storage.remove(TOKEN_KEY)
  ).subscribe(() => this.checkToken())
}

然后,该组件将订阅您的BehaviorSubject并执行您需要做的一切:

ngOnInit(): void {
  this.sub = this.authService.authenticationState$.pipe(
    switchMap((data) => {
      return data ? this.storage.get(USER_ID) : of(null)
    }),
    switchMap((id: any) => {
      this.id = id;
      return id ? this.userService.getUserDetails(id) : of(null)
    })
  ).subscribe(val => {
    // do stuff!
  })
}

ngOnDestroy() {
  this.sub.unsubscribe();
}

PS。不要使用any,将您的数据输入模型:)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Highchart-我必须刷新页面才能查看新数据

数组仅在刷新页面时获取数据

无需刷新页面即可获取数据

获取数据并提交而不刷新页面

Angular.js必须刷新页面才能看到更改

如何保持数据刷新页面?

为什么必须刷新页面才能使Telerik TabStrip在ASP.Net MVC 4中更新?

从数据库获取/获取数据,而无需刷新页面

我需要帮助才能在php页面上获取表单,以在提交时强制刷新页面

从Codeigniter中的数据库中获取数据,而无需刷新页面

从数据库中获取第一行会不断刷新页面

使用 firebase .on() 刷新页面后,仅从 firesbase 获取最后数据

在Django中每次刷新页面时获取一组不同的数据

从HTML表单获取数据到Microsoft Flow的方法,无需刷新页面也无需php

在 Next.js 中刷新页面后无法获取数据

Ajax从API加载数据,而无需单击或刷新页面

刷新页面后无法从express发送api响应数据以做出反应

如何刷新页面

刷新页面PopAsync()

刷新页面硒

刷新页面时不获取集合-AngularFire

刷新页面后如何获取路由参数?

刷新页面 Angular 7 后无法获取 /route

为什么仅在刷新React中的页面后才能从localStorage获取正确的数据

更新页面上的数据而不用 Vue 刷新?

刷新页面后调用数据(React Native Hooks)

在本地使用browserHistory刷新页面后,数据消失

刷新页面angular 8时丢失数据

更新页面上的数据而无需刷新