0

I am trying to configure a login but having some trouble with async/await and getters/setters. I can't seem to set the user values before the getter for the values is called back in the Login component.

I have this basic login function:

private async login() {
      await userModule.signIn({ username: this.username, password: this.pass })
      const usr = await userModule.isSignedIn
      console.log('Signed in:', usr) // comes back false

      if(usr) {
        this.goToDashboard()
      } else {
        alert('No user returned from user module')
        this.resetLogin()
      }     
  }   

Calls this function in the userModule

 @Action({ rawError: true })
  public async signIn(userInfo: { username: string; password: string }) {

    const { username, password } = userInfo;
    // Login API called here and works fine
    const { data } = await login("login", { username, password })

    // This alert confirms the sign in was successful
    alert(`Sign in from api ->  ${JSON.stringify(data)}`) 

    // Trying to set the token and user here with async/await
    await setToken(data.accessToken);
    await setUser(JSON.stringify(data.user))

    // This is the getter
    const theUser = await this.isSignedIn
    console.log('The User : ', theUser) // logs false
  }

The setters are pretty straight forward:

 @Mutation
  private setUser(_user: User): void {
    this.user = _user;
  }

  @Mutation
  private setToken(_token: string) {
    this.token = _token;
  } 

The getter part looks like this:

  user = getUser();
  token = getToken();

  get isSignedIn() {
    return this.user.email && this.token ? true : false;
  }

Here are the corresponding getters and setters in the other module. They basically save and retrieve the values from session storage if they exist and return empty if they not.

export function setToken(token: string): void {
  if (sessionStorage) {
    sessionStorage.setItem(SESSION_TOKEN_KEY, token);
  }
}

export function setUser(userData: string): void {
  if (sessionStorage) {
    sessionStorage.setItem(SESSION_USER_KEY, userData);
  }
}

export function getToken(): string {
  let token = "";
  if (sessionStorage) {
    const _token = sessionStorage.getItem(SESSION_TOKEN_KEY);
    token = _token ? _token : token;
  }
  return token;
}

export function getUser(): User {
  let user = {} as User;
  if (sessionStorage) {
    const userData = sessionStorage.getItem(SESSION_USER_KEY);
    user = userData ? (JSON.parse(userData) as User) : ({} as User);
    return user
  } 
  return user;
}

I am pretty new to Typescript and finding it a bit difficult working with getters and setters, especially with async operations. That said, I think I am not using the setters correctly. If anyone can help me out with this I'd much appreciate it.

mikeym
  • 5,705
  • 8
  • 42
  • 62
  • You may want to read up a bit on [How would one do async JavaScript getters and setters?](https://stackoverflow.com/questions/28790744/how-would-one-do-async-javascript-getters-and-setters/44578144). That being said, `isSignedIn` doesn't appear to need to be async anyway, so why are you awaiting it? – Seth Lutske Oct 27 '21 at 04:20
  • Thanks for the link. I will have a look over it and see if it can shed any more light on the problem. Regarding `isSignedIn`, the reason I have `await` on that is because the value needs to come back before the `if` statement that follows it can run the check. Does that not make sense? I have tried it without also of course but the value still comes back `false`. – mikeym Oct 27 '21 at 13:40
  • Its not making sense to me. You're await `isSignedIn`, which is just `return this.user.email && this.token ? true : false;`. It looks like that calls `getUser` and `getToken`, which in turn call to get some information from sessionStorage...where is the async in that call stack? – Seth Lutske Oct 27 '21 at 14:04
  • @SethLutske I guess that is the crux of the problem. I know there is no promises on them. I have tried to make them return promises but can't. In short I need to make the setters `await` so they are finished their business BEFORE `isSignedIn` is called (because it breaks my router). Right now the setters are not completed before the dash route is called and the router doesn't redirect to the page. Surely there is an easy way to fix this without hacky getters and setters? – mikeym Oct 27 '21 at 18:42
  • Getters and setters are nice, but it sounds like this is not a good use case for them, without bending over backwards like described in the post I linked. Perhaps just use regular async methods? – Seth Lutske Oct 27 '21 at 21:34
  • @SethLutske thanks for the suggestion. I decided to move another approach using `get userSignedIn()` in my root component. The routing is working better but the conditional rendering for my root component is broken. It takes a page refresh to display the sidebar and top bar. That is, the `get` is only called once on first load, before sign in, so returns false. It isn't called again post-sign in so the App.vue template, with top and side navs, don't display. It's very frustrating :S Any idea how I might fix this? Thanks! – mikeym Oct 29 '21 at 16:27

0 Answers0