2017-07-05 6 views
0

Ich möchte Geschichte der Produkte zu drucken. Ich habe eine ID des Produkts in ActivatedRoute.params. In der ngOnInit-Methode muss ich die gesamte Historie des Produkts abrufen und der Variablen zuweisen. Dann möchte ich Produkt zu ProductHistory zuordnen, weil ich letzte Version mit Geschichte zusammen haben möchte. Aber das Problem ist, Geschichte zu bekommen. Methode, um Geschichte zurück zu bekommen Versprechen und ich kann nicht die Länge von productsHistory bekommen, wenn ich diese Eigenschaft verwende und ich undefined. Wie kann ich diese Eigenschaft nach dem Laden vom Dienst erhalten?Angular - synchron von Promise

Ich möchte Methode nach der Ausführung getHistory() ausführen.

Mein Code:

ProductService.ts:

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

import 'rxjs/add/operator/toPromise'; 

// rest imports 

@Injectable() 
export class ProductService { 

    // URL to web api 
    private projectsUrl = 'http://localhost:8080/products'; 

    private headers = new Headers({'Content-Type': 'application/json'}); 

    constructor(private http: Http) {} 

    getHistory(id: number): Promise<ProductHistory[]> { 
     const url = `${this.projectsUrl}/projectId/${id}`; 
     return this.http.get(url) 
      .toPromise() 
      .then(response => response.json() as ProductHistory[]) 
      .catch(this.handleError); 
    } 

    handleError() { 
     //... 
     // implementation is irrelevant 
    } 
} 

ProductHistoryComponent.ts:

import { Component, Input, OnInit } from '@angular/core'; 
import { ActivatedRoute, Params } from '@angular/router'; 
import { Location } from '@angular/common'; 

import { ProductService } from './product.service'; 

import { ProductHistory } from './product-history'; 
import { Product } from './model/product'; 

import 'rxjs/add/operator/switchMap'; 

@Component({ 
    selector: 'product-history', 
    templateUrl: './product-history.component.html', 
    styleUrls: [ './product-history.component.css' ] 
}) 
export class ProductHistoryComponent implements OnInit { 

    auditProducts: ProductHistory[] = new Array<ProductHistory[]>();  
    selectedProduct: ProductHistory; 

    constructor(
     private route: ActivatedRoute, 
     private location: Location, 
     private productService: ProductService 
    ) {} 

    ngOnInit(): void { 
     let id: number = this.route.snapshot.params['id']; 

     this.productService.getHistory(id) 
      .then(history => this.historyProducts = history); 

     this.productService.getProduct(id) 
      .then(product => { 
       let lastVersion: ProductHistory = this.createLastVersion(product); 
       this.auditProducts.push(lastVersion); 
      }); 
    } 

    onSelect(ProductHistory: ProductHistory): void { 
     this.selectedProduct = ProductHistory; 
     this.compare(this.selectedProduct); 
    } 

    goBack(): void { 
     this.location.back(); 
    } 

    compare(history: ProductHistory): void { 
     let previous: ProductHistory; 
     if (history.changeNumber != null && history.changeNumber > 1) { 
      previous = this.historyProducts[history.changeNumber - 2]; 
      if (typeof previous != 'undefined') { 
       this.setPreviousDiffsFalse(previous); 
       if (previous.name !== history.name) { 
        history.nameDiff = true; 
       } 
       if (previous.price !== history.price) { 
        history.priceDiff = true; 
       } 
      } 
     } 
    } 

    createLastVersion(product: Product): ProductHistory { 
     let lastVersionProduct: ProductHistory = new ProductHistory(); 
     lastVersionProduct.id = this.historyProducts.length + 1; 
     lastVersionProduct.name = product.name; 
     lastVersionProduct.price = product.price; 
     lastVersionProduct.changeNumber = this.historyProducts[this.historyProducts.length - 1].changeNumber + 1; 
     return lastVersionProduct; 
    } 

    setPreviousDiffsFalse(previous: ProductHistory): void { 
     previous.nameDiff = false; 
     previous.priceDiff = false; 
    } 

} 
+4

Sie können einen Wert nicht synchron von einem Versprechen erhalten mehr als Sie einen Apfel von einer Orange bekommen. –

Antwort

1

Sie können es nicht synchron ausführen, Sie müssen auf jedes Versprechen warten, um ein Ergebnis zurückzugeben, bevor Sie etwas mit diesem Ergebnis tun können. Der normale Weg dazu besteht darin, Code innerhalb von then Blöcken zu verschachteln, wenn Sie Versprechungen verwenden. Alternativ können Sie auch async/await mit der neuesten Version von Typoskript verwenden, und Sie müssen nur Ihren Code component ändern, da Sie den Typ Promise bereits von Ihrem Dienst zurückgeben. Dies macht Code einfacher zu lesen (IMO), obwohl der emittierte JavaScript-Code immer noch Funktion/Callback-Verschachtelung (, wenn Sie ES7 zielen, glaube ich, wird möglicherweise jemand korrigieren oder bestätigen).

// note the use of async and await which gives the appearance of synchronous execution 
async ngOnInit() { 
    let id: number = this.route.snapshot.params['id']; 

    const history = await this.productService.getHistory(id); 
    this.historyProducts = history; 

    const product = await this.productService.getProduct(id); 
    let lastVersion: ProductHistory = this.createLastVersion(product); 
    this.auditProducts.push(lastVersion); 
} 
1

Ich würde vorschlagen, observables statt Versprechungen mit ... aber Ihre Frage zu beantworten, Sie müssen nur die zweite Anfrage nach die erste wird erhalten. Etwas wie folgt aus:

ngOnInit(): void { 
    let id: number = this.route.snapshot.params['id']; 

    this.productService.getHistory(id) 
     .then(history => { 
       this.historyProducts = history); 

       this.productService.getProduct(id) 
        .then(product => { 
         let lastVersion: ProductHistory = this.createLastVersion(product); 
         this.auditProducts.push(lastVersion); 
     }); 
    } 
} 

Ich zog die zweite Anforderung innerhalb die dann von der ersten Anfrage. HINWEIS: Ich habe das nicht syntaktisch überprüft.