【问题标题】:Getting an object array from an Angular service从 Angular 服务获取对象数组
【发布时间】:2017-03-08 11:42:44
【问题描述】:

我是 Angular(以及 Javascript)的新手。我编写了一个返回用户数组的 Angular 服务。从 HTTP 调用中检索数据,该调用以 JSON 格式返回数据。当记录从 HTTP 调用返回的 JSON 数据时,我可以看到这个调用成功并且返回了正确的数据。我有一个调用服务来获取用户的组件和一个显示用户的 HTML 页面。我无法从服务获取数据到组件。我怀疑我错误地使用了 Observable。也许我也错误地使用了订阅。如果我注释掉 ngInit 函数中的 getUsers 调用并取消注释 getUsersMock 调用,一切正常,我会看到 HTML 页面的列表框中显示的数据。我想将 JSON 数据转换为服务中的用户数组或列表,而不是从服务返回 JSON 并让组件对其进行转换。

从 HTTP 调用返回的数据以获取用户:

[
    {
        "firstName": "Jane",
        "lastName": "Doe"
    },
    {
        "firstName": "John",
        "lastName": "Doe"
    }
]

user.ts

export class User {
    firstName: string;
    lastName: string;
}

用户服务.ts

...
@Injectable
export class UserService {
    private USERS: User[] = [
        {
            firstName: 'Jane',
            lastName: 'Doe'
        },
        {
            firstName: 'John',
            lastName: 'Doe'
        }
    ];

    constructor (private http: Http) {}

    getUsersMock(): User[] {
        return this.USERS;
    }

    getUsers(): Observable<User[]> {
        return Observable.create(observer => {
            this.http.get('http://users.org').map(response => response.json();
        })
    }
...

user.component.ts

...
export class UserComponent implements OnInit {
    users: User[] = {};

    constructor(private userService: UserService) {}

    ngOnInit(): void {
        this.getUsers();
        //this.getUsersMock();
    }

    getUsers(): void {
        var userObservable = this.userService.getUsers();
        this.userObservable.subscribe(users => { this.users = users });
    }

    getUsersMock(): void {
        this.users = this.userService.getUsersMock();
    }
}
...

user.component.html

...
<select disabled="disabled" name="Users" size="20">
    <option *ngFor="let user of users">
        {{user.firstName}}, {{user.lastName}}
    </option>
</select>
...

!!!更新!!!

我一直在阅读“英雄”教程,但不适合我,所以我开始尝试其他方法。我已经按照英雄教程描述的方式重新实现了我的代码。但是,当我记录 this.users 的值时,它会报告 undefined。

这是我修改后的 user-service.ts

...
@Injectable
export class UserService {
    private USERS: User[] = [
        {
            firstName: 'Jane',
            lastName: 'Doe'
        },
        {
            firstName: 'John',
            lastName: 'Doe'
        }
    ];

    constructor (private http: Http) {}

    getUsersMock(): User[] {
        return this.USERS;
    }

    getUsers(): Promise<User[]> {
        return this.http.get('http://users.org')
            .toPromise()
            .then(response => response.json().data as User[])
            .catch(this.handleError);
    }
...

这是我修改后的 user.component.ts

...
export class UserComponent implements OnInit {
    users: User[] = {};

    constructor(private userService: UserService) {}

    ngOnInit(): void {
        this.getUsers();
        //this.getUsersMock();
    }

    getUsers(): void {
        this.userService.getUsers()
            .then(users => this.users = users);

        console.log('this.users=' + this.users); // logs undefined
    }

    getUsersMock(): void {
        this.users = this.userService.getUsersMock();
    }
}
...

!!!!!!!!!!最终工作解决方案!!!!!!!!!! 这是最终工作解决方案的所有文件:

user.ts

export class User {
    public firstName: string;
}

user.service.ts

import { Injectable }     from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable }     from 'rxjs/Observable';

import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';

import { User } from './user';

@Injectable()
export class UserService {
    // Returns this JSON data:
    // [{"firstName":"Jane"},{"firstName":"John"}]
    private URL = 'http://users.org';

    constructor (private http: Http) {}

    getUsers(): Observable<User[]> {
        return this.http.get(this.URL)
            .map((response:Response) => response.json())
                .catch((error:any) => Observable.throw(error.json().error || 'Server error'));
    }
}

user.component.ts

import { Component, OnInit }   from '@angular/core';
import { Router }              from '@angular/router';

import { User }        from './user';
import { UserService } from './user.service';


@Component({
    moduleId: module.id,
    selector: 'users-list',
    template:  `
        <select size="5">
            <option *ngFor="let user of users">{{user.firstName}}</option>
        </select>
    `
})

export class UserComponent implements OnInit{
    users: User[];
    title = 'List Users';

    constructor(private userService: UserService) {}

    getUsers(): void {
        this.userService.getUsers()
            .subscribe(
                users => {
                    this.users = users;
                    console.log('this.users=' + this.users);
                    console.log('this.users.length=' + this.users.length);
                    console.log('this.users[0].firstName=' + this.users[0].firstName);
                }, //Bind to view
                            err => {
                        // Log errors if any
                        console.log(err);
                    })
    }

    ngOnInit(): void {
        this.getUsers();
    }
}

【问题讨论】:

    标签: arrays json angular rxjs angular2-http


    【解决方案1】:

    看看你的代码:

     getUsers(): Observable<User[]> {
            return Observable.create(observer => {
                this.http.get('http://users.org').map(response => response.json();
            })
        }
    

    和来自https://angular.io/docs/ts/latest/tutorial/toh-pt6.html的代码 (顺便说一句。非常好的教程,你应该看看)

     getHeroes(): Promise<Hero[]> {
        return this.http.get(this.heroesUrl)
                   .toPromise()
                   .then(response => response.json().data as Hero[])
                   .catch(this.handleError);
      }
    

    Angular2 中的 HttpService 已经返回了一个 observable,所以你不需要像你在这里做的那样包装另一个 Observable:

       return Observable.create(observer => {
            this.http.get('http://users.org').map(response => response.json()
    

    尝试按照我提供的链接中的指南进行操作。仔细研究应该没问题。

    ---编辑----

    首先,您在哪里记录 this.users 变量? JavaScript 不是这样工作的。你的变量是未定义的,没关系,因为代码执行顺序!

    尝试这样做:

      getUsers(): void {
            this.userService.getUsers()
                .then(users => {
                   this.users = users
                   console.log('this.users=' + this.users);
                });
    
    
        }
    

    查看 console.log(...) 在哪里!

    尝试从 toPromise() 辞职,这似乎只适用于没有 RxJs 背景的 ppl。

    获取另一个链接:https://scotch.io/tutorials/angular-2-http-requests-with-observables 再次使用 RxJs observables 构建您的服务。

    【讨论】:

    • 你的观点是对的。考虑添加工作示例。
    • 您可以使用英雄教程中的工作示例。它工作得很好。 angular.io/resources/live-examples/toh-6/ts/plnkr.html
    • 感谢 jmachnik。我用其他信息更新了我的问题。我的代码看起来如此的原因是我最初按照英雄教程中的描述实现了它,但是在组件中我的 User[] 得到了“未定义”,所以我开始尝试其他事情。代码现在看起来像英雄教程,但我仍然不确定。有什么线索吗?
    • jmachnik,它现在正在工作。我很高兴您引用了“Observable”教程而不是“Promise”教程,因为我知道前者是我应该使用的(几乎取代了 Promise)。
    • jmachnik,它现在正在工作。我很高兴你引用了“Observable”教程而不是“Promise”教程,因为我知道前者是我应该使用的(几乎取代了 Promise)。起初,这仍然对我不起作用。我相信我有两个问题:1)我的模板有错误。我只是通过删除 HTML 文件并将 HTML 直接放在组件的 templateUrl 字段中并显然修复了一个未知问题才发现这一点。 2) 记录返回值。
    猜你喜欢
    • 1970-01-01
    • 2021-09-14
    • 2020-09-08
    • 2017-12-24
    • 2021-07-26
    • 2016-12-25
    • 1970-01-01
    • 1970-01-01
    • 2017-02-21
    相关资源
    最近更新 更多