Как бороться с асинхронной функцией в angular гуарах? - PullRequest
0 голосов
/ 13 февраля 2020

У меня есть проблема с асинхронной функцией сделки в асинхронной функции в angular guard, guard ниже первого возвращает неопределенное значение isLogged, а после этого истинного значения isLogged то, что я хочу вернуть. Может ли кто-нибудь помочь мне с этой простой проблемой?

export class AuthGuardService implements CanActivate {

  constructor(
    private router: Router
  ) { }
  canActivate(): Observable<boolean> | Promise<boolean> | boolean {
    if (this.checkIfUserIsLogged()) {
      return true;
    }
    this.router.navigateByUrl('/login');
    return false;
  }

  private checkIfUserIsLogged(): boolean {
    if (!window.indexedDB) {
      console.log(`Your browser doesn't support a stable version of IndexedDB.`);
    }
    let isLogged;
    const request = indexedDB.open(DB.NAME);
    request.onsuccess = () => {
      const userName = localStorage.getItem('user');
      const db = request.result;
      const tx = db.transaction(DB.OBJECT_STORE, 'readwrite');
      const store = tx.objectStore(DB.OBJECT_STORE);
      const logoutRequest = store.get(userName);
      logoutRequest.onsuccess = () => {
        console.log(logoutRequest.result.isLogged);
        logoutRequest.result.isLogged ? isLogged = true : isLogged = false;
      };
      return isLogged;
    };
    console.log(isLogged);
    return isLogged;
  }
}

Ответы [ 2 ]

0 голосов
/ 13 февраля 2020

Вам нужно вернуть либо обещание, либо наблюдаемое, так как вы выполняете какой-то асин c код, а затем немедленно его игнорируете.

Код в том виде, в каком он есть, будет эффективно игнорировать ваш onSuccess и всегда будет возвращать неопределенное («значение» isLogged);

Вместо этого верните наблюдаемое (аналог обещания - вернет результат в какой-то момент в будущем), а затем передайте значение в субъект изнутри обратный вызов onsuccess.

canActivate(): Observable<boolean> {
  // return an observable - a value that will return at some point in the future
  return this.checkIfUserIsLoggedIn().pipe(
    tap(loggedIn => {
      // it has now run. tap is one way of getting to the result and doing something
      if(!loggedIn) {
        this.router.navigateByUrl('/login');
      }
    });
  );
}

private checkIfUserIsLogged(): Observable<boolean> {
    if (!window.indexedDB) {
      console.log(`Your browser doesn't support a stable version of IndexedDB.`);
      return of(false);
    }

    const subject: Subject<boolean> = new Subject<boolean>();

    const request = indexedDB.open(DB.NAME);
    request.onsuccess = () => {
      const userName = localStorage.getItem('user');
      const db = request.result;
      const tx = db.transaction(DB.OBJECT_STORE, 'readwrite');
      const store = tx.objectStore(DB.OBJECT_STORE);
      const logoutRequest = store.get(userName);
      logoutRequest.onsuccess = () => {
        console.log(logoutRequest.result.isLogged);
        const isLogged = logoutRequest.result.isLogged;

        // Trigger the observable. The calling code will now run the pipe.
        subject.next(isLogged);
        subject.complete();
      };       
    };

    return subject.asObservable();        
  }
0 голосов
/ 13 февраля 2020

Когда вы работаете с асинхронным режимом, вы должны быть осторожны, потому что значение возвращается, когда функция обрабатывается, а не сразу, поэтому компиляция уходит до тех пор, пока значение не будет обработано. Я думаю, что ваша проблема здесь:

      private checkIfUserIsLogged(): boolean {
                    if (!window.indexedDB) {
                      console.log(`Your browser doesn't support a stable version of IndexedDB.`);
                    }
                    let isLogged=false; // start with false
                    const request = indexedDB.open(DB.NAME);
                    request.onsuccess = () => {
                      const userName = localStorage.getItem('user');
                      const db = request.result;
                      const tx = db.transaction(DB.OBJECT_STORE, 'readwrite');
                      const store = tx.objectStore(DB.OBJECT_STORE);
                      const logoutRequest = store.get(userName);
                      logoutRequest.onsuccess = () => {
                        console.log(logoutRequest.result.isLogged);
                        logoutRequest.result.isLogged ? isLogged = true : isLogged = false;
                return logoutRequest.result.isLogged; //you need to return now the value whe the on success is processed
                      };
return false;

                  };
    return false;
        }
...