user2415458
user2415458

Reputation: 29

Angular 2 Promise and refactoring

I just finished reading Clean Code, and am trying to refactor my Angular 2 code so that each of my function's does one thing like it states to do in that book, but I am having trouble with getting this to work and I think it comes down to a lack of understanding about promises in general. This is my current working version of the method.

    prepopulateUserInfoFromStorage() {
    var emailFromStorage;
    var passwordFromStorage;

    this._storage.ready().then(() => {
      this._storage.get('email').then((emailValue) => {
        emailFromStorage = emailValue;
      }).then(() => {
        this._storage.get('password').then((passwordValue) => {
          passwordFromStorage = passwordValue;

        })
      }).then(() => {
        if (emailFromStorage != null && passwordFromStorage != null) {

          (<FormControl>this.loginForm.controls['email']).setValue(emailFromStorage);
          (<FormControl>this.loginForm.controls['password']).setValue(passwordFromStorage);
        }
      });
    }).catch(function (error) {
    });
}

I've been trying to turn this single method into

var userInfo = this.getUserInfoFromStorage();
prepopulateUserInfo(userInfo);

Here is my latest attempt at those that fails. I believe the issue is related to when they are being called and when they are finishing their promises. My working code above I understand because none of the prepopulation is happening until after each promise, but I get lost with getting the proper functionality when I try to split them up. If anyone could help me here and hopefully explain conceptually what I am missing I'd appreciate it very much.

getUserInfoFromStorage() {
    var emailFromStorage;
    var passwordFromStorage;

    this._storage.get('email').then((emailValue) => {
        emailFromStorage= emailValue;
    }).then(()=>{
        this._storage.get('password')
        .then((passwordValue)=> {
            passwordFromStorage = passwordValue;
        })
    })

    return {email: emailFromStorage, password: passwordFromStorage};
  }

  prepopulateUserInfo(userInfo: any) {
    if (userInfo.email != null && userInfo.password != null) {
      (<FormControl>this.loginForm.controls['email'])
      .setValue(userInfo.email);

(this.loginForm.controls['password']) .setValue(userInfo.password); } }

Upvotes: 1

Views: 77

Answers (1)

JB Nizet
JB Nizet

Reputation: 691865

You first need to understand asynchronism. There is no way you can return information directly from an asynchronous method. You can only return a promise.

Second, you can combine two promises into one using Promise.all().

Finally, if you're calling then() inside a callback passed to a first then(), then there is a problem. Promises are designed to avoid that kind of pyramid of callbacks, by allowing to flattening them.

Although it's been written for AngularJS promises, I advise you to read this blog article I wrote, which explains several of the traps you fell into.

prepopulateUserInfoFromStorage() {
    this.getUserInfoFromStorage().then(info => this.prepopulateUserInfo(info));
}

prepopulateUserInfo(userInfo: any) {
  if (userInfo.email != null && userInfo.password != null) {
     (<FormControl>this.loginForm.controls['email']).setValue(userInfo.email);
     (<FormControl>this.loginForm.controls['password']).setValue(userInfo.password);
  }
}

getUserInfoFromStorage() {
  return this._storage.ready()
    .then(() => Promise.all([this._storage.get('email'), this._storage.get('password')])
    .then(array => {
      return {email: array[0], password: array[1]};
    });
}

Upvotes: 2

Related Questions