2017-02-02 1 views
0

Ich habe diese EventsStorage-Typescript-Klasse, die für das Speichern und Abrufen von Event-Objekten im ionischen Speicher verantwortlich ist (Wrapper für sqlite und indexedDB). Es verwendet meine Event-Klasse überall.Wie mache ich diese Klasse wieder verwendbar in Typoskript? Meta-Programmierung? Unterklassen? eingespritztes Modul?

Ich möchte viel von dieser Logik für etwas anderes als ein Ereignis, wie ein Widget wiederverwenden.

Ich komme aus einem Ruby-Hintergrund, wo es relativ einfach wäre, die gesamte Speicherlogik zu extrahieren, einen Ruby Var, der buchstäblich die Klasse Event ist, zu setzen und diese Variable zu verwenden, wo immer ich Event verwende. Kann ich etwas Ähnliches in Typoskript machen? Gibt es eine andere Mechanik, die ich verwenden kann, um den Großteil dieser Klasse für etwas anderes, wie Widget, wiederzuverwenden?

Idealerweise meine EventsStorage Klasse wird wirklich leicht, und ich bin nicht nur Anrufe zu this.some_storage_module.get_ids() oder this.some_storage_module.insert_new_objs() Einwickeln - was ich dies benötigt, um jede andere Instanz kopiert/eingefügt werden müssten.

Etwas wie folgt aus:

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

Hier ist die bestehende Klasse:

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

Sie können Klassen wie Sie in Ihrem Kommentar im ersten Code-Block angegeben erweitern: 'Klasse EventsStorage erweitert EntityStorage', siehe auch: http://www.typescriptlang.org/docs/handbook/classes.html – cyrix

+0

Ja, bewusst davon, aber es scheint, es gibt viel mehr, das in diesen Code wiederverwendbar als nur geht ... erweitert FooBaseClass – jsharpe

Antwort

1

Es scheint mir, wie Sie Generika verwenden wollen. Sie definieren im Grunde eine grundlegende Schnittstelle zwischen all den Dingen, die Sie speichern möchten, und Ihr Code sollte von dieser Schnittstelle abhängen. In Ihrem Code, soweit ich Ihnen sagen kann, verwenden Sie nur die id Eigenschaft.

So würde es aussehen, ein bisschen wie dieser

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> 

Sie können here mehr über Generika lesen.

Bearbeiten: 1 - über Unterklassen - Es ist in der Regel weniger bevorzugt. Wenn Ihre ItemsStorage-Klasse beim Umgang mit Ereignissen im Vergleich zu Widgets ein anderes Verhalten benötigt, ist das Unterklassifizieren die Lösung. Aber wenn Sie das gleiche Verhalten für jede Klasse haben, könnte man Ihren Code Generic aufrufen, und die Verwendung von Generika ist besser.

+0

Hmm, ich bin mir nicht sicher, dass es "ID" ist, die zwischen diesen Dingen geteilt wird. Diese Klassen stellen keine Instanz eines Widgets oder Events dar, sie speichern und rufen Blobs von Daten aus der Datenbank ab. Also, ich denke, es ist Speicher, der die eine Sache ist, die in der Oberklasse oder generisch instanziiert werden muss. Auch in Ihrem Beispiel scheint "Speicher" nicht definiert zu sein. – jsharpe

+0

Ich denke, das war ziemlich nah. Generika waren hilfreich – jsharpe

Verwandte Themen