2017-07-05 57 views
0

我想打印产品的历史记录。我在ActivatedRoute.params中有一个产品ID。在ngOnInit方法中,我必须获取产品的所有历史记录并将其分配给变量。然后,我想将产品映射到productHistory,因为我想要带历史记录的最后一个版本。但问题在于获得历史。获取历史记录的方法返回Promise和我无法获得产品历史的长度,当我使用此属性,我得到未定义。从服务中加载后怎样才能得到这个属性?Angular - 从Promise同步

我想执行getHistory()后执行方法。

我的代码:

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

无法从承诺中获得同步的价值,而不是从橙子获得苹果。 –

回答

1

您不能同步运行它,您必须等待每个承诺才能返回结果,然后才能使用该结果执行某些操作。正常的做法是在使用承诺时在then块中嵌套代码。或者,您也可以使用async/await以及最新版本的打字稿,并且您只需更改component代码,因为您已从服务中返回Promise类型。这使代码更容易阅读(IMO),虽然发出的JavaScript代码仍然会使用函数/回调嵌套(,除非您的目标是es7我相信,也许有人会更正或确认这)。

// 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

我会建议使用可观察的,而不是承诺......但回答你的问题,您只需在收到第一个请求后执行第二个请求。事情是这样的:

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); 
     }); 
    } 
} 

我刚搬到第二个请求当时的第一要求。注:我没有语法检查。