如何将Async Local Storage Observable转换为承诺并正确投射?
我正在尝试使用Angular Async Local Storage项目缓存一些服务数据: https://github.com/cyrilletuzi/angular-async-local-storage
数据正确保存到本地IndexDb(我在Chrome开发工具中查看过)。问题是我无法恢复数据。承诺解决了空洞。这是问题:
result => this._storage.getItem(this._objectKey).toPromise();
以下是完整来源的链接: https://github.com/GregFinzer/AmbientStateExample
以下是包含缓存的完整服务类:
// 3rd party imports
import { Injectable } from '@angular/core';
import { Http, Response, RequestOptions, Headers } from '@angular/http';
import { Observable, Subscription } from 'rxjs/Rx';
import { AsyncLocalStorage } from 'angular-async-local-storage';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
import 'rxjs/add/operator/do';
import {OnInit, OnDestroy} from '@angular/core';
// Our imports
import { Stock } from './stock-model';
@Injectable()
export class StockService {
private _url = 'http://finance.google.com/finance/info?client=ig&q=NASDAQ%3AAAPL,GOOG';
private _stocks: Promise<Stock[]>;
private _timer;
private _sub: Subscription;
private _lastStockCheckDate: Date;
private _objectKey = 'stocksObject';
private _dateKey = 'lastStockCheckDate';
private _tickInterval = 60000; // sixty seconds
constructor(private _http: Http, protected _storage: AsyncLocalStorage) {
this._timer = Observable.timer(this._tickInterval, this._tickInterval);
this._sub = this._timer.subscribe(t => { this.timerInterval(t); });
}
// This will not be hit, not sure how to implement in a service
ngOnDestroy() {
console.log('Destroy timer');
this._sub.unsubscribe();
}
timerInterval(tick) {
console.log('Interval hit: ' + tick);
this.processCache();
}
// Get the stocks from the actual service or from local storage cache
public getStockCache(): Promise<Stock[]> {
console.error('getStockCache()');
let result: Promise<Stock[]>;
// Call the service if we have not before
if (!this._lastStockCheckDate) {
result = this.getStocks();
this.saveToStorage(result);
this.updateLastCheckDate();
} else {
// Get the data from storage
result = <Promise<Stock[]>> this._storage.getItem(this._objectKey).toPromise();
}
return result;
}
private processCache(): void {
console.log('processCache()');
this._storage.getItem(this._dateKey).subscribe((lastStockCheckDate) => {
let now = new Date();
// Google has a maximum of 60 seconds between calls
if (lastStockCheckDate && (now.getTime() - lastStockCheckDate.getTime()) < this._tickInterval) {
return;
}
// Save the last check date
this.updateLastCheckDate();
// Get the stocks from the service
let serviceStockPromise: Promise<Stock[]> = this.getStocks();
// If anything changed, save to local storage
serviceStockPromise.then((serviceStocks) => {
this._storage.getItem(this._objectKey).subscribe((storageStocks) => {
if (this.anythingChanged(serviceStocks, storageStocks)) {
this._storage.setItem(this._objectKey, serviceStocks)
.subscribe(() => {}, () => {});
}
}, () => {});
});
}, () => {});
}
// Has anything changed from what was returned from the service vs what we have in local storage?
private anythingChanged(serviceStocks: Stock[], storageStocks: Stock[]): boolean {
console.log('anythingChanged()');
if (serviceStocks.length !== storageStocks.length) {
return true;
}
for (let i = 0; i < serviceStocks.length; i++) {
if (serviceStocks[i].l_cur !== storageStocks[i].l_cur) {
return true;
}
}
return false;
}
// Save what was returned from the service into local storage asynchronously
private saveToStorage(stocks: Promise<Stock[]>): void {
console.error('saveToStorage()');
stocks.then((data) => {
this._storage.setItem(this._objectKey, data)
.subscribe(() => {}, () => {});
});
}
// Update the last time we called the service
private updateLastCheckDate(): void {
console.error('updateLastCheckDate()');
const now = new Date();
this._lastStockCheckDate = now;
this._storage.setItem(this._dateKey, now).subscribe(() => {}, () => {});
}
// Get stocks from the service
private getStocks(): Promise<Stock[]> {
console.error('getStocks()');
return this._http.get(this._url, this.getRequestOptions())
.do((data: Response) => console.log('All: ' + data.text()))
// The substr is required because Google puts in two comment characters //
.map((response: Response) => <Stock[]> JSON.parse(response.text().substr(3)))
.toPromise();
}
// Write any errors out to the console
private handleError(error: Response) {
console.error(error);
let msg = `Error status code ${error.status} at ${error.url}`;
return Observable.throw(msg);
}
// Ensure we get JSON from the service
private getRequestOptions(): RequestOptions {
let opt: RequestOptions;
let myHeaders: Headers = new Headers;
myHeaders.append('Accept', 'application/json');
opt = new RequestOptions();
opt.headers = myHeaders;
return opt;
}
}