2017-06-18 26 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