我是Observables的新手。我正在使用它们来检查用户是否在我的根页的构造函数中登录。
为了做到这一点,我已经嵌套了许多Observable,并且它们工作正常,但我认为有一种方法可以压缩所有这些嵌套的Observable。
我只是希望您查看代码并让我知道可以改进的内容,以及我是否可以在login-page.ts
pages/login-page/login-page.ts
export class LoginPage {
constructor(public navCtrl: NavController, private userService: UserService, private storage: Storage) {
this.userService.getStoredToken().subscribe(
data => {
console.log('Token and username are stored.')
this.userService.checkTokenValidity(data[0], data[1]).subscribe(
() => {
console.log('Token and username and valid.')
// Go to the homepage
this.navCtrl.push(TabsPage)
}, err => {
console.log("Invalid token, trying the stored username and password.")
this.userService.getStoredUserAndPassFromStorage().subscribe(data => {
console.log('Successfuly retrieved the username and password')
this.userService.login(data[0], data[1]).subscribe((res) => {
console.log('Username and password are valid.')
// Go to the homepage
this.navCtrl.push(TabsPage)
// Save new user data to local storage
this.userService.authSuccess(res.access_token, data[0], data[1])
}, err => {
console.log("Failed to login using the stored username and password.")
//Remove the loading and show login form
})
}, err => {
console.log("No stored token.")
//Remove the loading the and login form
})
}
)
},
err => {
//Remove the loading the show login form
}
)
}

提供商/用户service.ts
export class UserService {
loginDetails: ILogin
headers: any
error: string
apiUrl = global.apiUrl
loginUrl = api.loginUrl
contentHeader: Headers = new Headers({'Content-Type': 'application/json'})
constructor(public http: Http, private storage: Storage) {
}
logout() {
this.storage.remove('_user')
this.storage.remove('_pass')
this.storage.remove('_token')
}
login(username: string, password: string): Observable<IAccessToken> {
this.loginDetails = {
client_id: global.clientId,
client_secret: global.clientSecret,
grant_type: 'password',
username: username,
password: password,
}
let body = JSON.stringify(this.loginDetails)
let options = new RequestOptions({headers: this.contentHeader})
return this.http
.post(this.loginUrl, body, options)
.map(response => response.json())
}
getStoredToken(): Observable<string[]> {
return Observable.forkJoin(
this.storage.get('_token'),
this.storage.get('_user')
)
}
getStoredUserAndPassFromStorage(): Observable<string[]> {
return Observable.forkJoin(
this.storage.get('_user'),
this.storage.get('_pass')
)
}
checkTokenValidity(token: any, username: any): Observable<IAccessToken> {
let params = new URLSearchParams()
params.set('access_token', token)
params.set('_format', 'json')
return this.http.get(api.userInfoUrl(username), {
search: params
}).map(response => response.json())
}
authSuccess(access_token, username, password) {
this.error = null
this.storage.set("_user", username)
this.storage.set("_pass", password)
this.storage.set("_token", access_token)
}
}
&#13;
答案 0 :(得分:1)
要从Observable传递参数并启动新的Observable,您可以使用switchMap
运算符。
在你的情况下,这将是
this.userService.getStoredToken().switchMap(data =>
this.userService.checkTokenValidity(data[0], data[1]).switchMap(isvalid =>
this.userService.getStoredUserAndPassFromStorage().switchMap(data =>
this.userService.login(data[0], data[1]).subscribe((res) => {
console.log('Username and password are valid.')
// Go to the homepage
this.navCtrl.push(TabsPage)
// Save new user data to local storage
this.userService.authSuccess(res.access_token, data[0], data[1])
}, err => {
console.log("Failed to login using the stored username and password.")
//Remove the loading and show login form
})
答案 1 :(得分:0)
感谢Alexander在这种情况下指出switchMap
的好处。
我已经使用了你的解决方案,并且我已经做了一些重构,以确保它尽可能的可读。
export class LoginPage {
login: ILogin
constructor(public navCtrl: NavController, private userService: UserService, private storage: Storage) {
this.forgotPasswordPage = ForgotPasswordPage
this.checkIfUserIsLoggedIn();
}
checkIfUserIsLoggedIn() {
const storedToken$ = this.userService.getStoredToken()
const checkTokenValidity$ = (data) => this.userService.checkTokenValidity(data[0], data[1])
const storedUserAndPass$ = this.userService.getStoredUserAndPassFromStorage();
const login$ = (data) => this.userService.login(data)
const checkStoredTokenValidity$ = storedToken$.switchMap(data => checkTokenValidity$(data))
const loginUsingStoredUsernameAndPass$ = storedUserAndPass$.switchMap(data => login$(data))
checkStoredTokenValidity$.subscribe(() => {
this.navCtrl.push(TabsPage)
}, () => {
console.log('Invalid token, now trying the saved username and password');
loginUsingStoredUsernameAndPass$.subscribe(res => {
this.navCtrl.push(TabsPage)
this.userService.updateToken(res.access_token)
}, () => {
console.log('Invalid stored username and pass, they possibly just got changed.')
//Remove the loading animation to show the login form.
})
})
}
}
恕我直言这是我能够根据switchMap
生成的最佳代码版本。如果有人能想到更好的版本,请提出建议。