无法读取每个未定义的属性

时间:2019-06-14 18:52:57

标签: angular2-observables

这个问题的标题只是我当前收到的错误,但是我真正需要帮助的是理解可观察性和API调用。无论出于什么原因,我只是无法很好地理解这个概念,我希望有人可能会给出最终解释。

我正在尝试创建一个新的Angular服务,该服务从API检索JSON。然后,我需要将响应映射到模型。由于命名约定古怪,因此此处的工作说明和工作要求可以互换使用。这是我的服务班。

import { CommunicationService } from './communication.service';
import { AiDescription } from '../models/ai-description.model';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';


@Injectable()
export class AiDescriptionService {

    requirements: Observable<AiDescription[]>;
    private aiDescriptionUrl: string = '/api/core/company/jobdescriptions';
    private dataStore: {
        requirements: AiDescription[]
    };
    private _requirements: BehaviorSubject<AiDescription[]>;
    private emptyRequestParams = {
        "company_id": "",
        "carotene_id": "",
        "carotene_version": "",
        "city": "",
        "state": "",
        "country": ""
    };

    readonly caroteneVersion: string = "caroteneV3";

    constructor(
        private communicationService: CommunicationService
    ) {
        this.dataStore = { requirements: [] };
        this._requirements = new BehaviorSubject<AiDescription[]>([]);
        this.requirements = this._requirements.asObservable();
    }

    LoadRequirements(params: Object) {
        this.communicationService.postData(this.aiDescriptionUrl, params)
        .subscribe(res => {
            let jobDescriptions = [];
            jobDescriptions = res.jobdescriptions;
            jobDescriptions.forEach((desc: { id: string; description: string; }) => {
                let aiDescription = new AiDescription();
                aiDescription.id = desc.id;
                aiDescription.description = desc.description;
            });
            this.dataStore.requirements = res;
            this._requirements.next(Object.assign({}, this.dataStore).requirements);
        });
    }

    CreateRequest(
        companyID : string,
        caroteneID : string,
        city: string,
        state: string,
        country: string
    ): Object {
        let newRequestParams = this.emptyRequestParams;
        newRequestParams.company_id = companyID;
        newRequestParams.carotene_id = caroteneID;
        newRequestParams.carotene_version = this.caroteneVersion;
        newRequestParams.city = city;
        newRequestParams.state = state;
        newRequestParams.country = country;
        this.LoadRequirements(newRequestParams);
        return this.dataStore;
    }

}

this.communicationService调用的postData()函数在这里:

  postData(url: string, jobInformation: any): Observable<any> {
    const start = new Date();
    const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
    const body = JSON.stringify(jobInformation);
    const options = { headers };

    return this.http.post(url, body, options)
      .catch(err => Observable.throw(err))
      .do(() => {
        this.analyticsLoggingService.TrackTiming('JobPostingService', 'PostSuccess', new Date().getTime() - start.getTime());
      }, () => {
        this.analyticsLoggingService.TrackError('JobPostingService', 'PostFailure');
      });
  }

我没有编写postData函数,因此无法对其进行修改。运行单元测试时,出现此错误:“ TypeError:无法读取未定义的属性'forEach'”。

除了简单地修复错误之外,我实际上还试图更好地理解使用Observables,这是我无法从其他来源获得的很好的理解。

1 个答案:

答案 0 :(得分:0)

在您的示例中,我建议用明确定义的模型替换anyObject

这是Angular 8的Subscription,Promise和Observable API调用的示例。您可以在此处获取更多信息:https://angular.io/tutorial/toh-pt6

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs';

import { User } from './user.model';

@Injectable({ providedIn: 'root' })
export class UserService {

    users: User[];

    authHeaders = new HttpHeaders()
        .set('Content-Type', 'application/json');

    constructor(
        private readonly http: HttpClient
    ) { }

    getUsers() {
        this.http.get(`https://myApi/users`, { headers: this.authHeaders })
            .subscribe(
                (data: User[]) => {
                    this.users = data;
                }, (error: HttpErrorResponse) => { /* handle error */ });
    }

    async getUserPromise(userID: number): Promise<User> {

        const url = `https://myApi/users/${userID}`;

        return this.http.get<User>(url, { headers: this.authHeaders })
            .toPromise();
    }

    getUserObservable(userID: number): Observable<User> {

        const url = `https://myApi/users/${userID}`;

        return this.http.get<User>(url, { headers: this.authHeaders });
    }

}

我喜欢将班级模型保存在单独的文件中。此示例的user.model.ts内容如下:

export class User {
    constructor(
        public id: number,
        public username: string,
        public displayName: string,
        public email: string
    ) { }
}

为了简洁起见,我没有包括身份验证标头或错误处理;但是,您可能需要根据需要添加它们。