如何使用可观察对象在 Angular2 中进行嵌套服务调用?
How to make nested Service calls in Angular2 using observables?
下面是我的组件文件和服务文件。我想做的是 after verification() 服务方法在它的成功回调中,即在订阅里面我想调用另一个服务方法即 signup()。但是,它无法正常显示以下错误:
以前在 angular1 中,如果我这样做会起作用,但在这里不起作用:
sampleService.meth1().success(function(){
//statement1...
sampleService.meth1().success(function(data){
//statement2...
}).error(function(){})
}).error(function(){});
})
Signup.component.ts
import { Component, Input } from '@angular/core';
import { Router } from '@angular/router';
import {User} from '../shared/model/user';
import {SignupService} from './signup.service';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/toPromise';
@Component({
moduleId: module.id,
selector: 'ym-signup',
templateUrl: 'signup.component.html',
styleUrls: ['signup.component.css'],
providers: [SignupService]
})
export class SignupComponent {
@Input()
user = {};
constructor(private router:Router, private signupService:SignupService) {
}
signup(selectedUser:User) {
this.signupService.verification(selectedUser)
.subscribe(data => {
swal({
title: 'Verify token sent on your Email.',
input: 'password',
inputAttributes: {
'maxlength': 10,
'autocapitalize': 'off',
'autocorrect': 'off'
}
}).then(function (password) {
this.signupService.signup(password)
.subscribe(data => {
localStorage.setItem('user', JSON.stringify(data));
this.router.navigate(['dashboard']);
},
error => alert(error));
})
},
error => alert(error));
}
goBack() {
this.router.navigate(['login']);
}
}
Signup.service.ts
import {User} from '../shared/model/user';
import { Headers, Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';
import {Injectable} from '@angular/core';
import {Response} from "angular2/http";
import { Observable } from 'rxjs/Observable';
@Injectable()
export class SignupService {
private postUrl:string = '/api/users/signup';
private verify:string = '/api/users/verify';
constructor(private http:Http) {
}
verification(user:User):Observable<JSON> {
let headers = new Headers({
'Content-Type': 'application/json'
});
return this.http
.post(this.verify, JSON.stringify(user), {headers: headers})
.map(this.extractData)
.catch(this.handleError);
}
signup(token:string):Observable<any> {
let headers = new Headers({
'Content-Type': 'application/json'
});
return this.http
.post(this.postUrl, JSON.stringify({verificationToken:token}), {headers: headers})
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body || { };
}
private handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg);
return Observable.throw(errMsg);
}
}
在注册方法中,您提供了一个 function 作为 then 的回调。
您应该改为使用箭头函数来保持相同的上下文。
signup(selectedUser:User) {
this.signupService.verification(selectedUser)
.subscribe(data => {
swal({
title: 'Verify token sent on your Email.',
input: 'password',
inputAttributes: {
'maxlength': 10,
'autocapitalize': 'off',
'autocorrect': 'off'
}
}).then(password => {
this.signupService.signup(password)
.subscribe(data => {
localStorage.setItem('user', JSON.stringify(data));
this.router.navigate(['dashboard']);
},
error => alert(error));
})
},
error => alert(error));
}
根据错误 Cannot read property 'signup' of undefined
判断,您似乎是在对一个不存在的对象调用 signup()
。
这是正确的,您将闭包创建为 .then(function (password) { ... })
,它不会捕获周围的上下文 this
,因此使用 this = window
调用,这不是您想要的显然。
参见:https://basarat.gitbooks.io/typescript/content/docs/arrow-functions.html
因此您可以使用箭头函数轻松修复它:
.then(password => {
this.signupService.signup(password)
.subscribe(data => {
localStorage.setItem('user', JSON.stringify(data));
this.router.navigate(['dashboard']);
}, error => alert(error));
})
使用 Observable.forkJoin() 来 运行 多个并发的 http.get() 请求。如果任何单个请求失败,整个操作将导致错误状态。
请在下面找到代码段用法:
</p>
<pre><code>getBooksAndMovies() {
Observable.forkJoin(
this.http.get('/app/books.json').map((res: Response) => res.json()),
this.http.get('/app/movies.json').map((res: Response) => res.json())
).subscribe(
data => {
this.books = data[0]
this.movies = data[1]
},
err => console.error(err)
);
下面是我的组件文件和服务文件。我想做的是 after verification() 服务方法在它的成功回调中,即在订阅里面我想调用另一个服务方法即 signup()。但是,它无法正常显示以下错误:
以前在 angular1 中,如果我这样做会起作用,但在这里不起作用:
sampleService.meth1().success(function(){
//statement1...
sampleService.meth1().success(function(data){
//statement2...
}).error(function(){})
}).error(function(){});
})
Signup.component.ts
import { Component, Input } from '@angular/core';
import { Router } from '@angular/router';
import {User} from '../shared/model/user';
import {SignupService} from './signup.service';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/toPromise';
@Component({
moduleId: module.id,
selector: 'ym-signup',
templateUrl: 'signup.component.html',
styleUrls: ['signup.component.css'],
providers: [SignupService]
})
export class SignupComponent {
@Input()
user = {};
constructor(private router:Router, private signupService:SignupService) {
}
signup(selectedUser:User) {
this.signupService.verification(selectedUser)
.subscribe(data => {
swal({
title: 'Verify token sent on your Email.',
input: 'password',
inputAttributes: {
'maxlength': 10,
'autocapitalize': 'off',
'autocorrect': 'off'
}
}).then(function (password) {
this.signupService.signup(password)
.subscribe(data => {
localStorage.setItem('user', JSON.stringify(data));
this.router.navigate(['dashboard']);
},
error => alert(error));
})
},
error => alert(error));
}
goBack() {
this.router.navigate(['login']);
}
}
Signup.service.ts
import {User} from '../shared/model/user';
import { Headers, Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';
import {Injectable} from '@angular/core';
import {Response} from "angular2/http";
import { Observable } from 'rxjs/Observable';
@Injectable()
export class SignupService {
private postUrl:string = '/api/users/signup';
private verify:string = '/api/users/verify';
constructor(private http:Http) {
}
verification(user:User):Observable<JSON> {
let headers = new Headers({
'Content-Type': 'application/json'
});
return this.http
.post(this.verify, JSON.stringify(user), {headers: headers})
.map(this.extractData)
.catch(this.handleError);
}
signup(token:string):Observable<any> {
let headers = new Headers({
'Content-Type': 'application/json'
});
return this.http
.post(this.postUrl, JSON.stringify({verificationToken:token}), {headers: headers})
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body || { };
}
private handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg);
return Observable.throw(errMsg);
}
}
在注册方法中,您提供了一个 function 作为 then 的回调。 您应该改为使用箭头函数来保持相同的上下文。
signup(selectedUser:User) {
this.signupService.verification(selectedUser)
.subscribe(data => {
swal({
title: 'Verify token sent on your Email.',
input: 'password',
inputAttributes: {
'maxlength': 10,
'autocapitalize': 'off',
'autocorrect': 'off'
}
}).then(password => {
this.signupService.signup(password)
.subscribe(data => {
localStorage.setItem('user', JSON.stringify(data));
this.router.navigate(['dashboard']);
},
error => alert(error));
})
},
error => alert(error));
}
根据错误 Cannot read property 'signup' of undefined
判断,您似乎是在对一个不存在的对象调用 signup()
。
这是正确的,您将闭包创建为 .then(function (password) { ... })
,它不会捕获周围的上下文 this
,因此使用 this = window
调用,这不是您想要的显然。
参见:https://basarat.gitbooks.io/typescript/content/docs/arrow-functions.html
因此您可以使用箭头函数轻松修复它:
.then(password => {
this.signupService.signup(password)
.subscribe(data => {
localStorage.setItem('user', JSON.stringify(data));
this.router.navigate(['dashboard']);
}, error => alert(error));
})
使用 Observable.forkJoin() 来 运行 多个并发的 http.get() 请求。如果任何单个请求失败,整个操作将导致错误状态。 请在下面找到代码段用法:
</p>
<pre><code>getBooksAndMovies() {
Observable.forkJoin(
this.http.get('/app/books.json').map((res: Response) => res.json()),
this.http.get('/app/movies.json').map((res: Response) => res.json())
).subscribe(
data => {
this.books = data[0]
this.movies = data[1]
},
err => console.error(err)
);