Reputation: 29
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
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