javascript - 使用 typescript 作为自定义数据类型在 Angular 中返回 Promise

标签 javascript json angular typescript

我是 Typescript 的新手,我正在尝试返回类型为 Device 的对象的 promise ,但我无法访问它。

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

当我在服务器中请求数据,然后我尝试在模板中打印它时,一切都消失了,在控制台中我有 Undefined。 函数 getDevices()device.component.ts 中的 console.log 也像对象的旧状态一样打印,因为当我更改数据时,会出现之前应该显示的数据。

我有几个问题,例如:

  1. 我如何访问 promise 的 .then 中的 response.json().data 以查看其结构或数据是什么它有?

  2. 我如何映射(我认为这个术语对于 Observable 是正确的,但我不知道如何为 Promise 说)我的 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
        }
    }
}

最佳答案

对于问题(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 来自服务器响应的对象。 (除非我错误地理解了这个问题)。

关于javascript - 使用 typescript 作为自定义数据类型在 Angular 中返回 Promise,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44620279/

相关文章:

javascript - 无法使用javascript库将css转换为rtl

c# - 如何为 web api 返回对象格式的数据?

java - 在java中解析序列化的json有效负载

node.js - 将 Angular Universal 部署到共享托管,无需 npm 或 node.js

javascript - Angular2和Electron访问browserWindwow对象

javascript - 在 ReactJS 中获取状态中的搜索值

javascript - 将包含单个反斜杠的 Javascript 字符串拆分为两个字符串

javascript - 如何在 Angular 4+ 中添加/使用 lightGallery 插件?

javascript - 如何排序隐藏一个 div 然后使用 jQuery 动画显示另一个?

javascript - 使用 Jquery 命名 JSON 数组