2016-04-13 4 views
1

Ich habe einige teure Versprechungen, die an verschiedenen Stellen aufgerufen werden. Im Idealfall würde Ich mag die Kette aus nur ein vorhandenen In-Flight-Versprechen (optional mit einer Kraft), so finde ich mich so etwas wie dies zu tun:Was ist das beste Swift-Muster für die Rückgabe eines ausstehenden PromiseKit-Versprechens, wenn man bereits läuft?

class Expensive { 
    var fooPromise : Promise<Foo>? 
    var barPromise : Promise<Bar>? 

    func doExpensiveFoo(force: bool = false) -> Promise<Foo> { 
    if let existing = fooPromise where existing.pending || (existing.fufilled && !force) { 
     // Return the existing promise 
     return existing 
    } 

    // Start a new Foo 
    return firstly { 
     // ... 
    } 
    } 

    func doExpensiveBar(force: bool = false) -> Promise<Bar> { 
    if let existing = barPromise where existing.pending || (existing.fufilled && !force) { 
     // Return the existing promise 
     return existing 
    } 

    // Start a new Bar 
    return firstly { 
     // ... 
    } 
    } 
} 

Aber das fühlt sich an wie eine angemessene Menge an Kesselblech (eine lokale Variable für jedes Versprechen, und der vorhandene Chunk am Anfang jeder Funktion), also frage ich mich, ob jemand ein gutes Muster zum Abstrahieren der Variablen und des Wrappers gesehen hat?

Um einen Begriff aus Python zu leihen, suche ich nach einem Dekorateur, der all das verstecken würde. So etwas wie:

class Expensive { 

    private func startFoo() -> Promise<Foo> { 
    return firstly { 
     //.. 
    } 
    } 

    public doExpensiveFoo = wrapExpensive(startFoo) 

} 

Irgendwelche Vorschläge, oder sollte ich mir das Rollen meiner eigenen anschauen?

Antwort

0

ich kein Experte bin, aber dieses Muster für mich gearbeitet:

private var fooPromise : Promise<Foo>? 

func doExpensiveFoo() -> Promise<Foo> { 
    if let fooPromise = self.fooPromise, fooPromise.isPending { 
     // return the pending promise 
     return fooPromise 
    } 

    // reassign a newly created promise 
    fooPromise = firstly { 
     // do your thing 
     ... 
    } 

    return fooPromise! 
    } 

Was ich über dieses Muster mag, ist, dass das Verfahren behandelt anhängig Status intern, und das Versprechen wird automatisch erneut ausgeführt, wenn es nach dem Abschluss aufgerufen wird. Dies ermöglicht Anrufern, den internen Mechanismus oder den Zustand des Versprechens zu ignorieren. Wenn Sie einen Anrufer benötigen, um an der Entscheidung mitzuwirken, sollten Sie den "Force" -Markierungsansatz beibehalten.

0

Ich sehe keine gemeinsame Basis von Foo und Bar in Ihrem Beispiel. Aber selbst wenn sie hätten einen Swift immer noch nicht unterstützt Kovarianz auf generische Typparameter. Zunächst müssen Sie für beide Typen ein gemeinsames Protokoll erstellen. Vielleicht hilft Ihnen auf dem richtigen Weg zu bekommen:

Storing generic objects in Swift Array

Verwandte Themen