2017-06-18 21 views
1

我是Typescript中的新成员,并且我试图返回承诺,并且类型为Device的对象,但我无法实现。返回Promice in Angular with typingcript as custom数据类型

问题是,当我返回一个模拟一切正常,但是当我连接到一个真正的API我在这里有问题response.json().data as Device

当我问服务器中的数据,然后我尝试在模板中打印它,它的一切消失了,并在控制台我有Undefined。 也是在device.component.ts在功能getDevices()打印像对象的旧状态,因为当我改变数据出现之前应该显示的数据。

我有这样几个问题:

  1. 如何访问到response.json().data在承诺的.then,看看有什么结构或什么的,它具有数据?

  2. 我该如何映射(我认为这个术语是正确的Observable,但我不知道怎么说它Promise S)我device与API的数据对象?

device.component.ts

import { Component, OnInit, Input } from '@angular/core'; 
import { Device } from './device'; 
import { DeviceService } from './device.service'; 

@Component({ 
selector: 'app-device', 
templateUrl: './device.component.html' 
}) 

export class DeviceComponent implements OnInit { 
    @Input() private device: Device; 
    constructor(private deviceService: DeviceService) {}; 

    ngOnInit(): void { 
     // this.getDevice(40072); 
     this.deviceService.getDeviceMock().then(device => this.device = device); 
    } 

    getDevice(id: number): void { 
     this.deviceService.getDevice(id).then(device => this.device = device); 
     console.log(this.device); 
     // this.deviceService.getDeviceMock().then(device => this.device = device); 
    } 

    search(id: number): void { 
     this.getDevice(id); 
} 

    save(): void { 
     this.deviceService.setDevice(this.device); 
    } 
} 

device.component.html

<input [(ngModel)]="idSearch" type="text" placeholder="Insert ID" > 
<button (click)="search(idSearch)">Search</button> 

<div *ngIf="device"> 
<div> 
    <label>Uid: </label> 
    <input [(ngModel)]="device.Uid" placeholder="Uid"> 
</div> 

<div> 
    <label>VigilId: </label> 
<input [(ngModel)]="device.VigilId" placeholder="VigilId"> 
</div> 

<div> 
    <label>CmfPhoneNumber: </label> 
    <input [(ngModel)]="device.Model.RuntimeSettings.CmfPhoneNumber" placeholder="CmfPhoneNumber"> 
</div> 

<div> 
    <label>ReportInterval: </label> 
    <input [(ngModel)]="device.Model.RuntimeSettings.ReportInterval" placeholder="ReportInterval"> 
</div> 

<div> 
    <label>GeoLocationHighAccuracy: </label> 
    <input [(ngModel)]="device.Model.RuntimeSettings.GeoLocationHighAccuracy" placeholder="GeoLocationHighAccuracy"> 
</div> 

<div> 
    <label>AlarmCancelTimeout: </label> 
    <input [(ngModel)]="device.Model.RuntimeSettings.AlarmCancelTimeout" placeholder="AlarmCancelTimeout"> 
</div> 

<div> 
    <label>AdherenceCheckInterval: </label> 
    <input [(ngModel)]="device.Model.RuntimeSettings.AdherenceCheckInterval" placeholder="AdherenceCheckInterval"> 
</div> 

<div> 
    <label>PreAlarmPeriod: </label> 
    <input [(ngModel)]="device.Model.RuntimeSettings.PreAlarmPeriod" placeholder="PreAlarmPeriod"> 
</div> 

<div> 
    <label>PingInterval: </label> 
    <input [(ngModel)]="device.Model.RuntimeSettings.PingInterval" placeholder="PingInterval"> 
</div> 

<button (click)="save()">Send</button> 

device.service.ts

import { Component } from '@angular/core'; 
import { Device } from './device'; 
import { Injectable } from '@angular/core'; 
import { Headers, Http } from '@angular/http'; 
import 'rxjs/add/operator/toPromise'; 

import { DeviceMock } from './device-mock' 


@Injectable() 
export class DeviceService { 
    // TODO: Create configuration file. 
    private apiUrl = 'https://api.com/api2/v2'; 
    private headers = new Headers({'Authorization': 'xxxx'}); 

    constructor(private http: Http) {}; 
    getDeviceMock(): Promise<Device> { 
     return Promise.resolve(DeviceMock) 
    } 

    getDevice(id: number): Promise<Device> { 
     const url = `${this.apiUrl}/device/${id}?names=RuntimeSettings`; 
     return this.http.get(url, {headers: this.headers}) 
      .toPromise() 
      .then(response => response.json().data as Device) 
      .catch(this.handleError); 
    } 

    setDevice(device: Device): Promise<Device> { 
     this.headers.set('Content-Type', 'application/json'); 
     const url = `${this.apiUrl}/device/${device.VigilId}?names=RuntimeSettings`; 
     return this.http.put(url, JSON.stringify(device), {headers: this.headers}) 
      .toPromise() 
      .then(response => response.json().data as Device) 
      .catch(this.handleError); 
    } 

    private handleError(error: any): Promise<any> { 
     console.error('An error occurred', error); 
     return Promise.reject(error.message || error); 
    } 
}; 

device.ts

export interface Device { 
    VigilId: number; 
    Uid: string; 
    Model: Model; 
}; 

interface Model { 
    RuntimeSettings: RuntimeSettings; 
}; 

interface RuntimeSettings { 
    ReportInterval: number; 
    PingInterval: number; 
    PreAlarmPeriod: number; 
    AdherenceCheckInterval: number; 
    AlarmClearTimeout: number; 
    AlarmCancelTimeout: number; 
    DailyReportInterval: number; 
    GeoLocationRetryCount: number; 
    GeoLocationHighAccuracy: true; 
    GeoLocationTimeOut: number; 
    GeoMaxAgeTimeOut: number; 
    CmfPhoneNumber: number; 
    PalmTouchTrigger: boolean; 
    TouchTriggerCooldownPeriod: number; 
    DemoMode: boolean; 
    DeviceName: string; 
    VerboseLogging: boolean; 
}; 

这是API

{ 
    "VigilId": 41, 
    "Uid": "Identi", 
    "Model": { 
     "RuntimeSettings": { 
      "ReportInterval": 900, 
      "PingInterval": 300, 
      "PreAlarmPeriod": 10, 
      "AdherenceCheckInterval": 3600, 
      "AlarmClearTimeout": 600, 
      "AlarmCancelTimeout": 15, 
      "DailyReportInterval": 43200, 
      "GeoLocationRetryCount": 3, 
      "GeoLocationHighAccuracy": true, 
      "GeoLocationTimeOut": 5000, 
      "GeoMaxAgeTimeOut": 60, 
      "CmfPhoneNumber": "", 
      "PalmTouchTrigger": true, 
      "TouchTriggerCooldownPeriod": 30, 
      "DemoMode": false, 
      "DeviceName": "", 
      "VerboseLogging": false 
     } 
    } 
} 
+0

这不是AngularJS的问题。 – estus

回答

1

对于问题(1)的响应:

你必须注意HTTP客户端请求是异步的。这意味着外/父功能不能等待网络请求完成,即不会阻止。这就是您在getDevices上获得“旧数据”的原因:它在从服务器响应中更新对象之前打印对象。

getDevice(id: number): void { 
    this.deviceService.getDevice(id) 
     .then(device => this.device = device); // network request is scheduled 
    console.log(this.device); // device is printed to log but not necessarily 
           // after the network request returns 
} 

为了解决这个问题,将其更改为:

getDevice(id: number): void { 
    this.deviceService.getDevice(id).then(device => { 
     console.log(device); // print to console what is returned from network 
     this.device = device; 
    }); 
} 

对于问题(2):

你在做什么this.device = device是正确的,这将更新您的this.device对象,并点它从服务器响应到新的device对象。 (除非我错误地理解了这个问题)。

+0

对于问题1,谢谢我现在明白了。 对于问题2,我认为我不知道为什么设备对象没有映射到promise的响应。 我需要饲料的对象,但当我做请求时,我的对象是undefined – Merlyn007

+0

那么,代码似乎对我来说是好的。网络响应后,您在此设备上看到什么?尝试使用'{{device | json}}'在视图模板上。 PS:删除设备属性中的“私人”访问修饰符,它需要在视图上访问,因此它不是“私人”的。 –

1

关于第二个问题,这条线:

response.json().data 

似乎在寻找所谓的“数据”的JSON的属性,但我没有看到你的榜样任何地方。返回的JSON是否有一个名为data的属性?

+0

非常感谢,也许昨天晚上我很清醒,我没有意识到,但我尽管改变了这一点。 – Merlyn007