2017-02-02 5 views
0

필자는 ionic-storage (sqlite 및 indexedDB 용 래퍼)에 Event 객체를 저장하고 검색하는이 EventsStorage typescript 클래스를 가지고 있습니다. 처음부터 내 이벤트 클래스를 사용합니다.이 클래스를 타이프 ​​크립트에서 재사용 가능하게 만드는 방법은 무엇입니까? 메타 프로그래밍? 하위 클래스? 주입 된 모듈?

위젯과 같이 이벤트 이외의 다른 용도로이 논리를 많이 사용하고 싶습니다.

나는 모든 스토리지 로직을 추출하기가 상대적으로 간단한 루비 배경에서 왔으며, 사실상 클래스 이벤트 인 ruby ​​var을 설정하고 Event를 사용할 때마다 그 var를 사용합니다. 타이프 스크립트로 비슷한 것을 할 수 있습니까? 위젯과 같은 다른 클래스에이 클래스의 대부분을 재사용 할 수있는 또 다른 메 커닉이 있습니까?

내 EventsStorage 클래스는 실제로 가벼워졌으며, 필요한 모든 다른 인스턴스에 복사/붙여 넣기해야하는 this.some_storage_module.get_ids() 또는 this.some_storage_module.insert_new_objs()으로 호출하는 것이 아닙니다. 이 같은

뭔가 :

export class EventsStorage { // extends BaseStorage (maybe??) 
    constructor(){ 
    super(Event, 'events'); // or some small set of magical args 
    } 
} 

가 여기에 기존 클래스입니다 : 당신이 제네릭을 사용하려면 같은

import { Injectable } from '@angular/core'; 
import { Storage } from '@ionic/storage'; 

import { Event }  from '../classes/event'; 

// EventsStorage < EntityStorage 
// - tracks local storage info 
// - a key to an array of saved objects 
// - a query() method that returns saved objects 

@Injectable() 
export class EventsStorage { 
    base_key: string; 
    ids_key: string; 

    constructor(
    private storage: Storage 
){ 
    this.base_key = 'event'; 
    this.ids_key = [this.base_key, 'ids'].join('_'); 
    } 

    get_ids(): Promise<any>{ 
    return this.storage.ready().then(() => { 
     return this.storage.get(this.ids_key).then((val) => { 
     if(val === null){ 
      return []; 
     } else { 
      return val; 
     } 
     }); 
    }); 
    } 

    insert_new_objs(new_objs: any): Promise<any>{ 
    return new_objs.reduce((prev: Promise<string>, cur: any): Promise<any> => { 
     return prev.then(() => { 
     return this.storage.set(cur._id, cur.event); 
     }); 
    }, Promise.resolve()).then(() => { 
     console.log('saving event_ids'); 
     return this.storage.set(this.ids_key, new_objs.map(obj => obj._id)); 
    }); 
    } 

    update(events: Event[]): Promise<any> { 
    let new_objs = events.map((event) => { 
     return { 
     _id: [this.base_key, event.id].join('_'), 
     event: event 
     }; 
    }); 

    return this.insert_new_objs(new_objs); 
    } 

    query(): Promise<Event[]>{ 
    let events = []; 
    return this.get_ids().then((ids) => { 
     return ids.reduce((prev: Promise<string>, cur: string): Promise<any> => { 
     return prev.then(() => { 
      return this.get_id(cur).then((raw_event) => { 
      events = events.concat([raw_event as Event]); 
      return events; 
      }); 
     }); 
     }, Promise.resolve()); 
    }); 
    } 

    get_id(id: string): Promise<Event>{ 
    return this.storage.get(id).then((raw_event) => { 
     return raw_event; 
    }); 
    } 
} 
+0

첫 번째 코드 블록에서 주석에 명시된대로 클래스를 확장 할 수 있습니다. '클래스 EventsStorage extends EntityStorage', 참조 : http://www.typescriptlang.org/docs/handbook/classes.html – cyrix

+0

예, 알고 있습니다. 하지만이 코드를 단지 재사용 할 수있는 것보다 더 많이 사용하는 것 같습니다 ... FooBaseClass를 확장하십시오 – jsharpe

답변

1

그것은 나에게 보인다. 기본적으로 저장하고자하는 모든 것들 사이에 기본적인 인터페이스를 정의하고 코드는 해당 인터페이스에 의존해야합니다. 귀하의 코드에서 내가 말할 수있는 한 id 속성 만 사용하십시오.

그래서 당신은 제네릭 here에 대한 자세한 내용을보실 수 있습니다이

import { Event } from '...'; 
import { Widget } from '...'; 
interface HasId{ 
    id: string; 
} 

class ItemsStorage<T extends HasId> { 
.... 
get_id(id: string): Promise<T>{ 
    ... 
} 
} 

const EventStorage = new ItemsStorage<Events>(storage); 
const WidgetStorage = new ItemsStorage<Widget>(storage); 
const ev = EventStorage.get_id('abc');  //type is Promise<Event> 
const wd = WidgetStorage.get_id('def'); //type is Promise<Widget> 

처럼 좀 보일 것이다.

편집 : 1 - 서브 클래 싱 정도 - 일반적으로 덜 바람직합니다. Events 대 Widgets을 처리 할 때 ItemsStorage 클래스가 다른 동작을 필요로한다면 서브 클래 싱이 솔루션입니다. 그러나 모든 수업에 대해 동일한 행동을 취하는 경우 코드 라고하며 제네릭을 사용하는 것이 좋습니다.

+0

흠, 나는이 것들 사이에서 공유되는 'id'라는 것이 확실하지 않습니다. 이 클래스는 위젯 또는 이벤트의 인스턴스를 나타내지는 않지만 DB에서 데이터 블록을 저장 및 검색합니다. 그래서, 나는 그것이 수퍼 클래스 또는 일반에서 인스턴스화 될 필요가있는 스토리지 중 하나라고 생각합니다. 또한 귀하의 예에서 '스토리지'는 정의되지 않은 것으로 보입니까? – jsharpe

+0

나는 이것이 아주 가깝다 고 생각한다. 제네릭이 도움이되었다. – jsharpe