2017-11-28 4 views
2

Um in einem Versprechen Rückruf nicht Codeblöcke zu umwickeln (eine Ebene des Einzugs speichern), ich folgendes irgendwann tun:Wie vermeidet man, Code in einen Versprechen Callback zu verpacken?

function myFunction() { 
    // Create the promise object and get the "resolve" callback 
    let promiseResolve = null; 
    const promise = new Promise((resolve, reject) => { 
     promiseResolve = resolve; 
    }); 

    // Then later in the code: 
    setTimeout(() => { 
     // Something slow 
     promiseResolve(); 
    }, 1000); 

    // And at the end 
    return promise 
} 

Es funktioniert, aber es fühlt sich ein bisschen chaotisch. Gibt es dafür ein geeignetes Muster in JavaScript?

+1

Ja, es ist chaotisch. Es gibt einfach keinen Grund zu vermeiden, den Code, der die Auflösung in den Promend-Executor-Callback tut. Da gehört es hin. – jfriend00

+0

Wenn Sie eine Einzugsebene speichern möchten und davon ausgehen, dass Sie keine Schließung benötigen, können Sie den Versprechungshauptteil immer in eine separate Funktion ausklammern. – Amadan

+0

Wenn Sie die Einrückungsstufe speichern möchten, führen Sie keine komplexe Logik in 'setTimeout' Callbacks durch, bei denen Ausnahmen nicht abgefangen werden. Verwenden Sie stattdessen 'return new Promise (auflösen => setTimeout (auflösen, 1000)). Then (() => {/ * etwas langsam * /});' – Bergi

Antwort

8

Gibt es ein passendes Muster in JavaScript?

Ja, das richtige Muster ist, was Sie anscheinend versuchen zu vermeiden.

function myFunction(data) { 
    return new Promise((resolve, reject) => { 
     // put code in here that calls resolve() or reject() 
     someAsyncOperation(data, function(err, result) { 
      if (err) { 
       reject(err); 
      } else { 
       resolve(result); 
      } 
     }); 
    }); 
} 

Für was Sie zeigt, gibt es nur wirklich keinen Grund, die resolve() oder reject() Handler außerhalb des Bereichs der Executor-Funktion zuzuweisen.

Hier sind einige der Vorteile, den Code innerhalb des Versprechen Testamentsvollstrecker zu halten:

  1. Es wird automatisch werfen sicher. Wenn Sie synchron innerhalb der Executor-Funktion (versehentlich) werfen, wird es automatisch gefangen und in eine Ablehnung für dieses Versprechen umgewandelt.
  2. Wenn Sie synchron in Ihren Code außerhalb der Prometheus-Executor-Funktion werfen, wird sie überhaupt nicht abgefangen und Ihre Funktion wird synchron ausgelöst. Es ist sehr schlecht, ein Versprechen zurückzugeben und synchron zu werfen, da dies den Anrufer sehr belastet, auf Fehler in zwei separaten Mechanismen zu achten.
  3. Sie machen keinen Grund dafür, warum Sie Ihrem Code Komplikation hinzufügen sollten, nur um zu vermeiden, dass Sie Code auf eine Einrückungsstufe setzen, die Sie ohnehin schon haben.
  4. Der Versprechen-Executor wurde aus einer Reihe guter Gründe so entworfen. Was Sie bevorzugen, ist im Wesentlichen das "Deferred" -Modell, in dem Sie ein Objekt erstellen, das Sie weitergeben können und auf dem Methoden zur Auflösung oder Zurückweisung angezeigt werden. Das ist absichtlich nicht das Design-Center für Versprechungen und es gab sehr gute Gedanken darüber, warum es nicht so ist, wie sie sich entschieden haben. Ich werde sehen, ob ich einige dieser Debatten und Diskussionen finden kann, aber ich weiß, dass ich sie gesehen habe und dass sie für mich Sinn ergeben.
  5. Es gibt sehr, sehr, sehr gelegentlich einige Gründe für eine Deferred-ähnliche Schnittstelle, wo der Code mit diesem Modell wesentlich einfacher ist. Sie können Ihr eigenes verzögertes Objekt mit dem Prometheus-Executor erstellen (was fast das ist, was Sie hier versuchen), aber es sollte wirklich nur dann gemacht werden, wenn ein Bedarf dafür besteht, nicht nur, weil Sie diesen Coding-Stil bevorzugen oder wollen um zu vermeiden, Code in den Executor Callback zu setzen.
  6. Sie haben eine Menge Rep hier, also ich rate, dass Sie ein ziemlich erfahrener Typ sind, also bin ich überrascht, dass Sie widerstehen, den Code in den Executor zu setzen, weil Javascript das LOT fördert. Es ist ein extrem verbreiteter Stil (mit anonymen Callbacks und Einbettung von Code-Logik in diese Callbacks). Selbst das Versprechen .then() und .catch() erfordern das. Um in Javascript zu programmieren, muss man daran gewöhnt sein und es erwarten. Dies ist häufig erforderlich, um auch auf übergeordnete Bereichsvariablen zugreifen zu können.
  7. Im Allgemeinen möchten Sie Callback- und Promise-Code nicht im selben Logikfluss mischen. Also, wenn ich eine Promise-Schnittstelle mit nicht-Versprechen-basierten Callback-Schnittstellen verwenden möchte, ist das erste, was ich tun, ich eine promisifizierte Schnittstelle für die Callback-Schnittstellen auf der niedrigsten Ebene möglich, so dass ich dann diese Schnittstelle vollständig mit einer Zusage verwenden kann Schnittstelle. In den meisten Fällen verwende ich einen automatisierten Weg, um die Schnittstelle zu promiformen, wie zum Beispiel util.promisify() oder Bluebird's Promise.promisifyAll().Dann besteht mein logischer Ablauf vollständig aus versprechungsbasierten Operationen und ich bin nie mit der Art von Code konfrontiert, den Sie zeigen, und jede Versuchung, Code wie diesen zu schreiben, ist auch weg.

Einige Referenzen:

Why does the Promise constructor need an executor?

Deferred Anti-Pattern

The Revealing Constructor Pattern

What's the correct pattern for Promise.defer?


Wenn Sie wirklich denken, dass Sie ein verzögertes Objekt "brauchen", dann würde ich vorschlagen, dass Sie diese Funktionalität in ein neues Objekt kapseln und verwenden, anstatt es bei jeder Verwendung manuell zu codieren. Bei all meinen Codierungen habe ich immer nur festgestellt, dass Code einfacher zu schreiben und sauberer mit einem verzögerten Objekt ist, und das war ein ziemlich ungewöhnliches System einer Low-Level-Warteschlange, das eine Menge verschiedener Aufgaben verwaltet.

Es gibt mehrere Beispiele für einfache, kurze Codeabschnitte zum Implementieren eines verzögerten Objekts. Hier ist eine:

Why does the Promise constructor need an executor?

+0

Froh, dass Sie 'promisify()' erwähnt haben, weil es ein Weg ist gehen Sie, falls jemand eine _ Bibliothek von Drittanbietern, die Async-Aufrufe von node-js style verwendet, gut ugh _ promisify_. –

Verwandte Themen