2017-02-02 5 views
0

私はこのイベントストアのtypescriptクラスを持っています。このクラスは、イオンストレージ(sqliteおよびindexedDBのラッパー)にEventオブジェクトを格納および取得するクラスです。それは私のイベントクラス全体で使用されます。このクラスをtypescriptで再利用できるようにするにはどうすればよいですか?メタプログラミング?サブクラス?注射されたモジュール?

ウィジェットのように、イベント以外のものにこのロジックをたくさん再利用したいと思います。

私は、すべてのストレージロジックを抽出するのが比較的簡単なルビーのバックグラウンドから来ています。文字通りクラスEventである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

最初のコードブロックで、コメントに記載されているようなクラスを拡張することができます: 'class 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からデータのブロブを保存および取得します。だから、スーパークラスやジェネリックでインスタンス化する必要があるストレージというストレージだと思います。また、あなたの例では、 'storage'は未定義のようですか? – jsharpe

+0

これはかなり近いとわかりました。ジェネリックは役に立ちました – jsharpe

関連する問題