Angular 2 组件无法从服务中检索数据 [英] Angular 2 component cannot retrieve data from service

查看:22
本文介绍了Angular 2 组件无法从服务中检索数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

情况很简单 - 我试图从 Angular 2 服务获取数据,但目标数组始终为空.我可以看到对 api 的调用返回数据和状态 200,并且控制台中没有错误.这是我的基本服务:

import {Injectable} from "@angular/core";从@angular/http"导入 {Http, Response};@Injectable()导出类数据服务{项目 = [];构造函数(私有 http:Http){this.loadItems();}加载项(){this.http.get('http://localhost:58928/api/front').map((res: 响应) => {返回 res.json();})}}

这里是组件:

import {Component, Input} from '@angular/core';从./../../services/data-service"导入{DataService};@成分({选择器:'项目列表',模板:`<div class="容器"><div class="items" *ngFor="let item of items|sort:'DESC';let i = index;trackBy: item?.id"><a href="/items/{{item.id}}"><mdl-card class="demo-card-square" mdl-shadow="2" mdl-card-expand><mdl-card-media><img src="{{item.imgUrl}}" alt="{{item.name}}" style="max-width: 100%"></mdl-card-media><mdl-card-title mdl-card-expand><h2 mdl-card-title-text>{{item.name}}</h2></mdl-card-title><mdl-card-supporting-text>{{item.shortDescription}}</mdl-card-supporting-text><mdl-card-actions mdl-card-border><h6 class='mdl-color-text--grey-600'>От {{item.priceFrom}} рублей.</h6></mdl-card-actions></mdl-card></a>

`,样式: [`.容器 {显示:弹性;弹性方向:行;flex-wrap: 包裹;justify-content: 空间环绕;对齐内容:空间环绕;对齐项目:拉伸;宽度:100%;}.项目{保证金:自动;填充顶部:1%;填充底部:1%;}一种 {文字装饰:无;}`]})导出类 ItemsList {@Input() items = [];构造函数(私有数据服务:数据服务){this.items = dataService.items;}}

解决方案

基本上,当你这样做时:

@Injectable()导出类数据服务{项目 = [];构造函数(私有 http:Http){this.loadItems();}加载项(){this.http.get('http://localhost:58928/api/front').map((res: 响应) => {返回 res.json();})}}

您调用 Web API 并仅映射结果,但不将其分配给任何内容.也许你可以像这样修改它:

@Injectable()导出类数据服务{项目 = [];构造函数(私有 http:Http){this.loadItems();}加载项(){this.http.get('http://localhost:58928/api/front').map((res: 响应) => {返回 res.json();}).subscribe(data => this.items = data);}}

这一次,只要有数据,items 就会包含它们.但是,这样做并不是最佳选择,因为您的组件可能在 HTTP 调用完成之前加载,在这种情况下,您也会得到一个空数组.最好的方法是要么返回 observable(由 map 返回)并使您的组件订阅它,要么创建一个在 items 初始化时触发的新 observable.

这是第一种可能性的示例:http://plnkr.co/edit/DD8fqa2dJGksCtOlolO2?p=预览

这种方法有效,唯一的问题是如果您调用loadItems"两次,则 HTTP 调用将执行两次.如果您想要一些缓存,则必须使用 Observables 开发更高级的东西.

The situation is quite simple - I'm trying to get data from Angular 2 service but target array is always empty. I can see that call to api return data and status 200 and there is no errors in console. Here is my basic service:

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

@Injectable()
export class DataService {
    items = [];
    constructor(private http:Http) {
        this.loadItems();
    }
    loadItems() {
        this.http.get('http://localhost:58928/api/front')
            .map((res: Response) => {
                return res.json();
            })
    }
}

And here is component:

import {Component, Input} from '@angular/core';
import {DataService} from './../../services/data-service';

@Component({
    selector: 'items-list',
    template: `
        <div class="container">
    <div class="items" *ngFor="let item of items|sort:'DESC';let i = index;trackBy: item?.id">
    <a href="/items/{{item.id}}">
        <mdl-card class="demo-card-square" mdl-shadow="2" mdl-card-expand>
        <mdl-card-media>
        <img src="{{item.imgUrl}}" alt="{{item.name}}" style="max-width: 100%">
         </mdl-card-media>
            <mdl-card-title mdl-card-expand>
                <h2 mdl-card-title-text>{{item.name}}</h2>
            </mdl-card-title>
            <mdl-card-supporting-text>
                {{item.shortDescription}}
            </mdl-card-supporting-text>
            <mdl-card-actions mdl-card-border>
                <h6 class='mdl-color-text--grey-600'>От {{item.priceFrom}} рублей.</h6>
            </mdl-card-actions>
        </mdl-card>
        </a>
    </div>
</div>
`,
    styles: [
        `
.container {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: space-around;
    align-content: space-around;
    align-items: stretch;
    width: 100%;
}

.items{
    margin: auto;
    padding-top: 1%;
    padding-bottom: 1%;
}

a {
text-decoration: none;
}

`
    ]
})

export class ItemsList {
    @Input() items = [];
    constructor(private dataService: DataService) {
        this.items = dataService.items;
    }
}

解决方案

Basically, when you do this:

@Injectable()
export class DataService {
    items = [];
    constructor(private http:Http) {
        this.loadItems();
    }
    loadItems() {
        this.http.get('http://localhost:58928/api/front')
            .map((res: Response) => {
                return res.json();
            })
    }
}

You call your web API and just map the result, but you don't assign it to anything. Maybe you can modify it like this:

@Injectable()
export class DataService {
    items = [];
    constructor(private http:Http) {
        this.loadItems();
    }
    loadItems() {
        this.http.get('http://localhost:58928/api/front')
            .map((res: Response) => {
                return res.json();
            }).subscribe(data => this.items = data);
    }
}

This time, as soon as the data are there, items will contain them. However, doing this like this is not optimal because it could be that your component loads before the HTTP call is done, and in this case, you'll get an empty array as well. The best would be to either returns the observable (return by map) and make your component subscribed to it or create a new observable that fires when items are initialized.

Here is an example of the first possibility: http://plnkr.co/edit/DD8fqa2dJGksCtOlolO2?p=preview

This approach works, this only thing is that if you call "loadItems" twice, the HTTP call will be done twice. If you want some caching, something more advanced have to be developped with Observables.

这篇关于Angular 2 组件无法从服务中检索数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆