1

我正在使用 Angular 2 和 Ionic 2,试图构建一系列反应对象。

我试图找出正确的方法来构建一个离子列表组件(StocksList),该组件通过一个简单的服务(StocksListService)来填充自己,该服务实例化新的可观察(Stock)类实例,这些实例从服务(StockService)获取数据在 Observable.interval 上重复调用 API。

最终,我希望能够创建一个有状态的管道来对 Stocks[] 进行排序(并且我想了解实际正确的方法来做我正在做的事情)。

我真的不知道如何更简洁地解释我的意图,所以我希望我的代码能帮助澄清情况:

——</p>

首页
^
股票列表组件 < 股票列表服务
^
股票组件 < 股票服务

——</p>

主页——</p>

主页.html

<ion-content>
  <ion-list
    stocksListCmp ></ion-list>
</ion-content>

主页.ts

@Page({
  templateUrl: 'build/pages/home/home.html',
  directives: [StocksList],
  providers: [StocksListService]
})

export class HomePage {
  constructor(public nav: NavController) { }
}

股票列表组件—</p>

股票-list.tpl.html

<ion-card
  [stockCmp]="stock"
  *ngFor="#stock of stocks; #i = index"></ion-card>

股票列表.component.ts

@Component({
  selector: '[stocksListCmp]',
  viewProviders: [StocksListService, StockService]
})

@View({
  templateUrl: 'build/components/stocks-list/stocks-list.tpl.html',
  directives: [Stock]
})

export class StocksList {
  stocks: Observable<IStock>[]; // not sure if my typing is correct here, or anywhere with advanced types really

  constructor(private stocksListService: StocksListService) { }

  ngOnInit() {
    this.stocks = this.stocksListService.stocks;
  }

}

股票-list.service.ts

let tickers: string[] = ['AAPL', 'BTCUSD=X', '^DJI', '^GSPC', 'NFLX', 'TSLA'];

@Injectable()
export class StocksListService {

  constructor( @Inject(forwardRef(() => StockService)) private stockService: StockService) { }

  get stocks(): Observable<IStock>[] {
    return tickers
      .map((ticker) => new Stock(this.stockService.init(ticker))); // getting type error on this.stockService.init(ticker): Observable<Observable<IStock>> not assignable to StockService
  }

}

库存组件—</p>

stock.tpl.html

<ion-card-content>
  <ion-row>
    <ion-col>{{ stock?.ticker }}</ion-col>
    <ion-col>{{ stock?.price }}</ion-col>
    <ion-col>{{ stock?.chg_percent}}</ion-col>
  </ion-row>
</ion-card-content>

stock.component.ts

@Component({
  selector: '[stockCmp]',
  inputs: ['stockCmp'],
  viewProviders: [StockService]
})

@View({
  templateUrl: 'build/components/stock/stock.tpl.html'
})

export class Stock {
  stockCmp: Stock; // not sure how to type here
  stock: IStock; // not sure how to type here

  constructor(private stockService: StockService) { }

  ngOnInit() {
    this.stockCmp['stockService']['init']
      .subscribe((data) => this.stock = data,
      null,
      () =>
        this.stockCmp['stockService']['update']
          .subscribe((service) => service
          .subscribe((data) => this.stock = data))
      );
  }

}

stock.service.ts

let source: Observable<number> = Observable.interval(60 * 1000).publish().refCount();

@Injectable()
export class StockService {

  constructor(private http: Http) { }

  public init(ticker: string): Observable<Observable<IStock>> {
    if (ticker) {
      let url = 'http://finance.yahoo.com/webservice/v1/symbols/' + ticker + '/quote?format=json&view=detail';
      return this.updateData(url);
    }
  }

  private loadData(url: string): Observable<IStock> {
    return this.http.get(url)
      .map((res) => this.mapData(res.json().list.resources[0].resource.fields));
  }

  private mapData(data: any): IStock {
    return {
      ticker: data.symbol,
      name: data.name,
      price: JSON.parse(data.price),
      chg_percent: JSON.parse(data.chg_percent) / 100,
      ts: data.ts
    };
  }

  public updateData(url: string): Observable<Observable<IStock>> {
    return { init: this.loadData(url), update: source.map(() => this.loadData(url)) }; // type error
  }

  private logError(error) {
    console.log(error);
  }

}

股票.d.ts

export interface IStock {
  ticker: string;
  name: string;
  price: number;
  chg_percent: number;
  ts: number;
}

所以这实际上现在工作得很好,但我确信这不是正确的方法。在第一次间隔调用之前,必须有更好的方法从 loadData 方法中获取结果。

我想了解在构建离子列表、实例化新类实例和使用响应式扩展方面的正确方法,希望这将帮助我实现一个有状态的管道来对股票列表进行排序。

非常感谢任何建议!如果我遗漏了任何内容或需要澄清任何内容,请告诉我。谢谢!

4

0 回答 0