【问题标题】:How to make nested Service calls in Angular2 using observables?如何使用 observables 在 Angular2 中进行嵌套服务调用?
【发布时间】:2017-01-27 01:42:02
【问题描述】:

下面是我的组件文件和服务文件。我想做的是在它的成功回调上的 after verify() 服务方法,即在订阅里面我想调用另一个服务方法,即注册()。但是,它无法向我显示以下错误:

以前在 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

标签: angular typescript rxjs observable rxjs5


【解决方案1】:

从错误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));
})

【讨论】:

  • 谢谢它起作用了我没想到是sweetalert导致了这个问题。如果您可以在验证()成功后提供帮助,还有一件事我想提示用户输入,然后在调用之前将该输入放入 signup() 方法中。
  • 好吧,在调用 this.signupService.signup(password)... 之前,最容易使用 JavaScript 的标准 prompt() 函数向用户询问凭据,该函数显示一个弹出窗口。见w3schools.com/jsref/met_win_prompt.asp 然后使用signup()方法中的值
【解决方案2】:

在注册方法中,您将 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));
        }

【讨论】:

    【解决方案3】:

    使用 Observable.forkJoin() 运行多个并发 http.get() 请求。如果任何单个请求失败,整个操作将导致错误状态。 请在下面找到 sn-p 的用法:

    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)
            );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-08
      • 1970-01-01
      • 2017-06-08
      • 1970-01-01
      • 2019-01-01
      • 1970-01-01
      • 2016-08-31
      • 1970-01-01
      相关资源
      最近更新 更多