值 return 无法读取未定义的 属性 'value'

Value return Cannot read property 'value' of undefined

我是 angular 的超级新手,所以我不知道是否有人回答了这个问题。我查看了一些答案,但无法正确回答。抱歉,如果这个问题已经得到回答。

我有一个调用后端 Rest 的 Angular 服务 API

export class StudentService {
    private studentUrl: string;

    constructor(private httpClient: HttpClient) {
        this.studentUrl = 'someurl';
    }

    public getTag(email: string): Observable < PayLoad > {
        const params = new HttpParams().set("email", email);
        return this.httpClient.get < PayLoad > (this.studentUrl.concat("Tag"), {
            params
        });
    }

    getCoursesForStudent(tag: string): Observable < CourseDto > {
        const params = new HttpParams().set("tag", tag);
        return this.httpClient.get < CourseDto > (this.studentUrl.concat('courses'), {
            params
        })
    }

    getStudentByEmail(email: string): Observable < any > {
        const params = new HttpParams().set("email", email.toString());
        return this.httpClient.get < Student > (this.studentUrl.concat('getstu'), {
            params
        })
    }
}

而且我还有一个使用它的组件

export class StudentprofileComponent implements OnInit {
    courses: Observable < CourseDto > ;
    student: Student;
    newstu: Student;
    tag: PayLoad;
    payload = PayLoad;

    constructor(private studentservice: StudentService, private router: Router) {}

    loadCourses() {
        payload: new PayLoad();
        const email = atob(localStorage.getItem('stuemail'));
        this.studentservice.getTag(email).subscribe(data => {
            this.tag = data,
                console.log("data:" + data.value)
        });
        return this.studentservice.getCoursesForStudent(this.tag.value);
    }

    loadStudent() {
        let email = atob(localStorage.getItem('email'));
        return this.studentservice.getStudentByEmail(email.toString());
    }

    ngOnInit() {
        this.loadStudent().subscribe(data => {
                this.student = data
            }, error =>
            console.log(error));
        this.courses = this.loadCourses();
    }

}

问题是,我不断收到 TypeError Cannot read 属性 'value' of undefined。甚至数据也打印在控制台中。

这是一个异步调用。你不知道服务器什么时候会 return 这个 get-endpoint-

的答案

您使用函数 .subscribe() 订阅了通话。 在您订阅的那一刻,get 将尝试到达后端。

订阅函数中的所有内容都将在 returned 时执行。

//1.register subscription
    this.studentservice.getTag(email).subscribe(
data=>{
//3. will be executed when server answers
this.tag = data , 
    console.log("data:"+data.value)});

//2. Will return the value before the tag-object is set in subscribe
    return this.studentservice.getCoursesForStudent(this.tag.value);

所以你遇到的问题是,当你调用 return 所在的行时,标签对象仍然未定义,因为订阅还没有 returned。

您可以尝试在订阅内执行 getCoursesForStudent,但这会使它变得更复杂。

您可以尝试使用 switchmap 在另一个完成时订阅 observable https://www.learnrxjs.io/learn-rxjs/operators/transformation/switchmap

嵌套订阅是一种反模式,应该避免。尝试使用 switchMap 运算符来获取您需要的值。

export class StudentprofileComponent implements OnInit {
    courses: CourseDto ; // Removed the Observable due to new subscription
    student: Student;
    // newstu: Student;
    // tag: PayLoad;
    // payload = PayLoad;

    constructor(private studentservice: StudentService, private router: Router) {}

    // loadCourses() {
    //     payload: new PayLoad();
    //     const email = atob(localStorage.getItem('stuemail'));
    //     this.studentservice.getTag(email).subscribe(data => {
    //         this.tag = data,
    //             console.log("data:" + data.value)
    //     });
    //     return this.studentservice.getCoursesForStudent(this.tag.value);
    // }

    // loadStudent() {
    //     let email = atob(localStorage.getItem('email'));
    //     return this.studentservice.getStudentByEmail(email.toString());
    // }

    ngOnInit() {
        const email = atob(localStorage.getItem('email')).toString();
        const stuEmail = atob(localStorage.getItem('stuemail')).toString();

        this.studentservice.getStudentByEmail(email).subscribe(student => this.student = student);

        this.studentservice.getTag(stuEmail).pipe(
            switchMap(tag => this.studentservice.getCoursesForStudent(tag.value))
        ).subscribe(courses => this.courses = courses);
        
    }

}