2017-07-05 81 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); 
     }); 
    } 
} 

我剛搬到第二個請求當時的第一要求。注:我沒有語法檢查。