我是 Observables 新手。我使用它们来检查用户是否在我的根页面的构造函数中登录。
为了做到这一点,我嵌套了许多 Observables,它们工作得很好,但我认为有一种方法可以展平所有这些嵌套的 Observables。
我只是想让你检查一下代码,让我知道哪些地方可以改进,以及我是否可以在 login-page.ts
中压平这些 Observables
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
}
)
}
providers/user-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)
}
}
最佳答案
要传递参数并从 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
})
关于javascript - 如何在 Angular 2 中展平嵌套的 Observables,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40203789/