2016-02-20 52 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); 

希望这将帮助一些人。