2016-02-20 51 views
25

我有一個組件通過http獲取服務中的數據,問題是我不想在每次顯示此組件時都點擊API後端。我希望我的服務能夠檢查數據是否在內存中,如果是,則返回一個帶內存數組的observable,如果沒有,則發出http請求。Angular2:將數組轉換爲Observable

我的組件

import {Component, OnInit } from 'angular2/core'; 
import {Router} from 'angular2/router'; 

import {Contact} from './contact'; 
import {ContactService} from './contact.service'; 

@Component({ 
    selector: 'contacts', 
    templateUrl: 'app/contacts/contacts.component.html' 
}) 
export class ContactsComponent implements OnInit { 

    contacts: Contact[]; 
    errorMessage: string; 

    constructor(
    private router: Router, 
    private contactService: ContactService) { } 

    ngOnInit() { 
    this.getContacts(); 
    } 

    getContacts() { 
    this.contactService.getContacts() 
         .subscribe(
         contacts => this.contacts = contacts, 
         error => this.errorMessage = <any>error 
         ); 
    } 
} 

我的服務

import {Injectable} from 'angular2/core'; 
import {Http, Response, Headers, RequestOptions} from 'angular2/http'; 
import {Contact} from './contact'; 
import {Observable} from 'rxjs/Observable'; 

@Injectable() 
export class ContactService { 

    private contacts: Array<Contact> = null; 

    constructor (private http: Http) { 

    } 

    getContacts() { 
    // Check first if contacts == null 
    // if not, return Observable(this.contacts)? <-- How to? 

    return this.http.get(url) 
        .map(res => <Contact[]> res.json()) 
        .do(contacts => { 
         this.contacts = contacts; 
         console.log(contacts); 
        }) // eyeball results in the console 
        .catch(this.handleError); 
    } 


    private handleError (error: Response) { 
    // in a real world app, we may send the server to some remote logging infrastructure 
    // instead of just logging it to the console 
    console.error(error); 
    return Observable.throw(error.json().error || 'Server error'); 
    } 
} 

回答

44

你說得對。如果已經有內存中的數據,則可以使用of可觀察值(相當於RxJS 4中的return/just)。

getContacts() { 

    if(this.contacts != null) 
    { 
     return Observable.of(this.contacts); 
    } 
    else 
    { 
     return this.http.get(url) 
      .map(res => <Contact[]> res.json()) 
      .do(contacts => this.contacts = contacts) 
      .catch(this.handleError); 
    } 
} 
+0

它像一個魅力工作!非常感謝! – Mathius17

+0

這可能是一個愚蠢的問題,但不能只緩存observable本身並調用.next()而不是緩存狀態並在每次調用時重新創建observable? –

+0

好點,我會試試。雖然我不是最好的,因爲當我想迭代數組以返回一個特定鍵的聯繫人時 – Mathius17

0

這可能會很晚,但我一直在使用sessionStorage來處理一些工作。如果因爲人們四處奔波而失去狀態,你仍然有數據。

getSubjects(): Observable<Subject[]> { 
 
    
 
    let SubjectsString = sessionStorage.getItem("Subjects") 
 

 
    if (SubjectsString) { 
 
     let subjects: Subject[] = JSON.parse(SubjectsString); 
 
     console.log("GETTING DATA FROM SESSION STORAGE") 
 
     return Observable.of(subjects); 
 
     
 
    } else { 
 
     let url = `${this.apiHost}/api/subject`; 
 
     return this.http.get(url) 
 
     .map(res =>{   
 
    
 
      sessionStorage.setItem("Subjects",JSON.stringify(res.json()));   
 
      return res.json(); 
 
     }) 
 
     
 
     
 
    } 
 

 
     
 
    }

在這個例子中,我已經得到了主題和apiHost定義一個類,但其餘的是非常簡單的。您將該服務稱爲可觀察項。你的組件不知道數據在哪裏,它不關心。該服務會檢查本地存儲器,如果存在,它會將其轉換爲可觀察對象並返回它,如果不存在,它會去獲取它,然後將其保存到本地存儲器中,然後將其返回。

就我而言,我有幾百個頁面的巨大應用程序。用戶可能會從一個漂亮的新的Angular4頁面跳出,到一個典型的ASP時代,然後再次多次。讓sessionstorage中的所有菜單項和搜索結果一直是一個救星。

0

快速這裏的解決方案:

getSomething():Observable<Object[]>{ 
     return new Observable(observable => { 
      this.http.get('example.com').subscribe(results => { 
       observable.next(results.json()); 
       observable.complete(); 
      }); 
     }); 
    } 
0

有些人喜歡我希望它有所不同,這是由string[]Observable<string>

這是涉及到轉換的示例:

import { from } from 'rxjs/observable/from'; 
import 'rxjs/add/operator/map'; 
import 'rxjs/add/operator/toArray'; 

const ids = ['x12', 'y81']; 
let userUrls: string[]; 

from(ids) // Converting string[] into Observable<string> 
    .map(id => 'http://localhost:8080/users/' + id) 
    .toArray() 
    .subscribe(urls => userUrls = urls); 

希望這將幫助一些人。