2016-04-05 6 views
1

Ich hinterlasse meine synchrone, Multi-Thread-Java-Programmierwelt und die single-threaded, asynchrone, Versprechen-basierte Welt von ES6 JavaScript. Ich musste dieses Konzept der Mapping-Funktionen, die synchron zu asynchronen, auf Versprechen basierenden Funktionen geschrieben wurden, verstehen. Ich verwende derzeit eine Mischung aus ES6-Promises und Bluebird-Versprechen.Wie kann ich den Rest der "then" in einer Versprechungskette umgehen, wie eine traditionelle "Return" -Anweisung?

ich mit einem Beispiel beginnen würde die Grundlage für meine Frage (synchrone Beispiele in Java, Asynchron-Beispiele in ES6) einzustellen:

Synchron-Funktion

private Object doSomething(Object var1, Object var2) { 
    Object var3 = blockingFunction(var1); 
    Object var4 = anotherBlockingFunction(var2, var3); 
    return var4; 
} 

Asynchronous Versprechen-basierten equivlanet

function doSomething(var1, var2) { 
    return asyncFunction(var1) 
    .then(var3 => { 
     return anotherAsyncFunction(var2, var3); 
    }) 
    .then(var4 => { 
     return var4; 
    }); 
} 

ihr jetzt E ist meine Frage: Gibt es eine saubere (d. h. eingebaute, bereits gedacht) Möglichkeit, die synchrone return Idee zu simulieren, um den Rest der Rückholkette zu umgehen?

Um zu erklären, hier sind zwei weitere synchrone und asynchrone Beispiele:

Synchron-Funktion

private Object doSomething(Object var1, Object var2) { 
    Object var3 = blockingFunction(var1); 
    Object var4 = anotherBlockingFunction(var2, var3); 
    if (!var4.isValid()) { 
     return var3; 
    } 
    // If var4.isValid() equates to false, we bypass the following statements 
    // and return the value of var3 as the final value 
    Object var5 = var4.validateObject(); 
    var5.setSomething(var1); 
    return var5; 
} 

(Meine Vermutung auf ein) Asynchronous Versprechen-basierte Äquivalent

function doSomething(var1, var2) { 
    // Predefine variables within this block so they persist between 'then's 
    let var3; 
    let var4; 
    let var5; 
    let bypassCondition; 
    return asyncFunction(var1) 
    .then(result => { 
     var3 = result; 
     return anotherAsyncFunction(var2, var3); 
    }) 
    .then(result => { 
     var4 = result; 
     bypassCondition = !var4.valid; 
     if(bypassCondition) { 
      return var3; 
     } 
    }) 
    .endChain(bypassCondition) 
    // If the bypassCondition is true, the entire chain would return the value 
    // of the previous then's return; 
    // Otherwise, if false, the chain continues 
    .then(() => { 
     return var4.validateObject(); 
    }) 
    .then(result => { 
     var5 = result; 
     var5.something = var1; 
     return var5; 
    }); 
} 

Gibt es so etwas schon?

Ich bin diese Alternativen bewusst, so kann ich vielleicht gesagt, ob auch nicht wirklich der richtige Weg ist, es zu tun:

  • eine Ausnahme in der Mitte der Kette werfen und es am Ende fängt so, dass andere Aussagen umgangen
  • Wrap jeweils nachfolgenden then ‚s-Funktion in einem if (!bypassCondition) Block, so dass sie alle
+2

Setzen Sie alle nachfolgenden 'then' im' 'else' Block". Es gibt kein frühes Verlassen von Versprechensketten, das nur mit Funktionen funktioniert. Sie können jedoch eine Async-Funktion verwenden. – Bergi

+0

@Bergi danke für diesen Link. Ich war auf Ihre Antwort auf die Frage gestoßen, die Sie zuvor verlinkt hatten, aber ich habe nicht verstanden, dass dies eine Lösung für meine Frage war, bis Sie sie mit dieser spezifischen Frage verknüpft haben. Obwohl ich zustimmen würde, dass es sich um ein Duplikat handelt, möchte ich um der Vollständigkeit willen eine Antwort schreiben, so dass klar ist, wie ich erreichen soll, was ich versuche zu tun. Ist das möglich? –

+0

Ich bin froh, dass ich geholfen habe, indem ich den Link gesetzt habe :-) Es gibt tatsächlich [viele weitere ziemlich ähnliche Fragen] (https://stackoverflow.com/search?q=break+chain+ [promise]). Ich denke, normalerweise erlauben wir keine Antworten, um Fragen zu duplizieren, aber ich habe wieder geöffnet, damit Sie die Frage beantworten können (https://stackoverflow.com/help/self-answer). Bitte setze einfach einen Satz wie "Diese Antwort hier [Link] hat mir geholfen" an die Spitze und lass mir eine Verbesserung :-) – Bergi

Antwort

1

This answer over here ist, wo ich meine Antwort auf diese Frage erhalten konnte.

Wie Bergi darauf hingewiesen hat, verzweigt sich das, was ich hier mache.

function doSomething(var1, var2) { 
    // Predefine variables within this block so they persist between 'then's 
    let var3; 
    let var4; 
    let var5; 
    return asyncFunction(var1) 
    .then(result => { 
     var3 = result; 
     return anotherAsyncFunction(var2, var3); 
    }) 
    .then(result => { 
     var4 = result; 
     if(!var4.valid) { 
      return var3; 
     } 
     else { 
      return Promise.resolve() 
      .then(() => { 
       return var4.validateObject(); 
      }) 
      .then(result => { 
       var5 = result; 
       var5.something = var1; 
       return var5; 
      }); 
     }) 
    } 
} 

Grundsätzlich Sie nicht ein Versprechen Kette stoppen: Alles, was ich tun müssen, ist die anhaltende Zweig innerhalb den else-Block, wie so setzen. Auch wenn es so aussieht, als ob ich in der Lage sein sollte, denken Sie daran, dass andere Funktionen .then(...) an die Ausgabe Ihrer Funktion anhängen werden. Der Code hat keine Unterscheidung, ob die then Anweisungen innerhalb einer Funktion oder außerhalb davon erscheinen, so was ich vorgeschlagen hatte, .endchain(...), würde alle anderen Benutzer der Versprechen Kette außerhalb der der Funktion beenden müssen, so dass die Kette letztlich nicht nutzbar.

diese Verzweigung Methode mit dem traditionellen return Verhalten, das ich nach dem erreicht wird, war, weil die letzten then in einer Kette vor dem Ende der Funktion ist, wo die Kette abholen, wenn der Rückgabewert außerhalb der Funktion verwendet wird — in diesem Fall, entweder nach return var3;, wenn var4.valid ist false, oder nach return var5; sonst.

1

Sie sprechen über bedingtes Fluss in Versprechen Ketten nicht ausgeführt werden, von denen e Arly Return ist ein nützlicher Geschmack.

Ja, das ist möglich, indem Sie Ihre Kette bedingt verzweigen. Halten Sie ein Auge auf die Klammer:

function doSomething(var1, var2) { 
    return asyncFunction(var1) 
    .then(var3 => anotherAsyncFunction(var2, var3)) 
    .then(var4 => (!var4.isValid())? var3 : var4.validateObject() 
    .then(var5 => (var5.something = var1, var5))); 
} 

Hinweis den Einzug in die letzte Zeile, wo die .then weg von var4.validateObject() ist.

Diese Karten ganz gut zu ES7 (wo wir eine frühe Kaution zu booten tun können):

async function doSomething(var1, var2) { 
    let var3 = await asyncFunction(var1); 
    let var4 = await anotherAsyncFunction(var2, var3); 
    if (!var4.isValid()) { 
    return var3; 
    } 
    let var5 = await var4.validateObject(); 
    var5.something = var1; 
    return var5; 
} 

(Sie nicht angeben, ob validateObject waren async oder nicht, so ging ich mit async).

+0

Nach Bergis Vorschlag, asynchrone Funktionen auszuprobieren, sehe ich jetzt, dass sie letztlich das erreichen, was ich versuche machen. Versprechen mögen so viel besser sein als einfache alte Rückrufe, aber asynchrone Funktionen scheinen so viel besser zu sein als Versprechen, weil ich das sequentielle Paradigma nicht vollständig verlassen muss. Sie können nicht früh genug Unterstützung erhalten! –

+0

@MichaelPlautz beachten Sie, dass asynchrone Funktionen sind nur syntaktische Zucker auf Versprechen, so dass sie Hand in Hand gehen (z. B. "asyncFunction" oben gibt wirklich ein Versprechen). Zum Beispiel kann 'Promise.all' usw. immer noch in asynchronen Funktionen verwendet werden, um Dinge parallel auszuführen, selbst im sequentiellen Bereich. – jib