Wie überprüfe ich, ob ein Objekt ein Promise ist?

Lesezeit: 9 Minuten

Benutzer-Avatar
theram

Egal ob ES6 Promise oder ein Bluebird PromiseQ Promiseetc.

Wie teste ich, ob ein bestimmtes Objekt a ist Promise?

  • Bestenfalls könntest du nach a suchen .then Methode, aber das würde Ihnen nicht sagen, dass das, was Sie haben, definitiv ein Versprechen ist. Alles, was Sie an diesem Punkt wissen würden, ist, dass Sie etwas haben, das a aufdeckt .then Methode, wie ein Versprechen.

    – Scott Offen

    2. Januar 2015 um 17:56 Uhr


  • @ScottOffen die Versprechenspezifikation ausdrücklich macht keinen Unterschied.

    – Benjamin Grünbaum

    2. Januar 2015 um 17:57 Uhr

  • Mein Punkt ist, dass jeder ein Objekt erstellen kann, das a exponiert .then Methode, die kein Versprechen ist, sich nicht wie ein Versprechen verhält und nicht die Absicht hatte, wie ein Versprechen verwendet zu werden. Suche nach a .then Methode sagt Ihnen nur, dass das if-Objekt nicht haben eine .then Methode, dann du nicht ein Versprechen haben. Das Gegenteil – dass die Existenz von a .then Methode bedeutet, dass Sie tun ein Versprechen haben – muss nicht unbedingt wahr sein.

    – Scott Offen

    2. Januar 2015 um 18:06 Uhr


  • @ScottOffen Per Definition ist die nur Ein etablierter Weg, um ein Versprechen zu identifizieren, besteht darin, zu prüfen, ob es einen hat .then Methode. Ja, das birgt das Potenzial für Fehlalarme, aber es ist die Annahme, auf die sich alle Versprechungsbibliotheken verlassen (denn das ist alles, was sie kann sich verlassen auf). Soweit ich sehen kann, besteht die einzige Alternative darin, den Vorschlag von Benjamin Gruenbaum zu übernehmen und ihn durch die Promise-Testsuite laufen zu lassen. Aber das ist für den tatsächlichen Produktionscode nicht praktikabel.

    – JLRishe

    25. Januar 2015 um 17:49 Uhr


  • const isPromise = v => typeof v === 'object' && typeof v.then === 'function'

    – Dominik

    16. Januar 2021 um 3:29 Uhr


Benutzer-Avatar
Benjamin Grünbaum

Wie eine Versprechungsbibliothek entscheidet

Wenn es eine hat .then Funktion – das ist die nur Verwendung von standardmäßigen Promise-Bibliotheken.

Die Promises/A+-Spezifikation hat einen Begriff namens thenfähig, was im Grunde “ein Objekt mit a then Methode”. Versprechen werden und sollten sich anpassen irgendetwas mit einer Then-Methode. Alle von Ihnen erwähnten Versprechungsimplementierungen tun dies.

Betrachten wir die Spezifikation:

2.3.3.3 wenn then eine Funktion ist, rufen Sie sie mit x wie folgt auf, erstes Argument resolvePromise und zweites Argument returnPromise

Es erklärt auch die Gründe für diese Designentscheidung:

Diese Behandlung von thenables ermöglicht die Interoperabilität von Promise-Implementierungen, solange sie Promises/A+-kompatibel sind then Methode. Außerdem ermöglicht es Promises/A+-Implementierungen, nicht konforme Implementierungen mit angemessenen then-Methoden zu „assimilieren“.

Wie Sie sich entscheiden sollten

Sie sollten nicht – sondern anrufen Promise.resolve(x) (Q(x) in Q), das wird stets Konvertieren Sie einen beliebigen Wert oder extern thenfähig in ein vertrauenswürdiges Versprechen. Dies ist sicherer und einfacher, als diese Überprüfungen selbst durchzuführen.

Ja wirklich müssen sicher sein?

Durchlaufen kann man es immer die Testsuite 😀

  • Wie informiert Sie die Ausführung von Promise.resolve(x) (Q(x) in Q), ob x ein Promise ist oder nicht?

    – Ben

    23. Januar 2021 um 5:47 Uhr

  • @Ben tut es nicht, du willst dich fast nie darum kümmern, ob etwas ein Versprechen ist oder nicht – Promise.resolve erledigt das automatisch für Sie – Sie bekommen immer eine Zusage.

    – Benjamin Grünbaum

    23. Januar 2021 um 17:58 Uhr

  • @BenjaminGruenbaum Aber warum Promise.resolve(a_promise) würde die geben a_promise?

    – Onkeltem

    1. April um 0:00 Uhr

  • Auch in der async Kontext await thing macht es entweder zu lösen things Wert oder zu seinem versprochen Wert.

    – Onkeltem

    1. April um 0:17


Das Überprüfen, ob etwas vielversprechend ist, verkompliziert den Code unnötig, verwenden Sie einfach Promise.resolve

Promise.resolve(valueOrPromiseItDoesntMatter).then(function(value) {

})

  • @AlexMills ja, es funktioniert sogar für nicht standardmäßige Versprechen wie das jQuery-Versprechen. Es kann fehlschlagen, wenn das Objekt eine Then-Methode hat, die eine völlig andere Schnittstelle als Promise Then hat.

    – Esailija

    10. Januar 2016 um 8:35 Uhr

  • Diese Antwort, obwohl vielleicht ein guter Rat, beantwortet die Frage nicht wirklich.

    – Stijn de Witt

    15. März 2016 um 23:16 Uhr

  • Sofern es bei der Frage nicht wirklich darum geht, dass jemand tatsächlich eine Promise-Bibliothek implementiert, ist die Frage ungültig. Nur eine Promise-Bibliothek müsste die Prüfung durchführen, danach können Sie immer ihre .resolve-Methode verwenden, wie ich gezeigt habe.

    – Esailija

    16. März 2016 um 9:23 Uhr

  • @Esalija Die Frage scheint mir relevant und wichtig zu sein, nicht nur für einen Implementierer einer Versprechensbibliothek. Es ist auch relevant für a Benutzer einer Promise-Bibliothek, die wissen möchte, wie sich Implementierungen verhalten/sollten/könnten und wie verschiedene Promise-Bibliotheken miteinander interagieren. Insbesondere ist dieser Benutzer sehr bestürzt über die offensichtliche Tatsache, dass ich ein X für jedes X versprechen kann, außer wenn X “Versprechen” ist (was auch immer “Versprechen” hier bedeutet – das ist die Frage), und ich bin definitiv interessiert genau zu wissen, wo die Grenzen dieser Ausnahme liegen.

    – Don Hatch

    21. Oktober 2016 um 13:08 Uhr

  • @Esailija Ich habe eine Variable, die angibt, ob der Code geladen ist oder nicht. Diese Variable könnte ein Versprechen sein, das anzeigt, dass es geladen wird, worauf ich warten sollte, oder ein Wert, der anzeigt, dass es geladen ist, damit ich es richtig rendern kann. Erwähnenswert ist, dass ich eine Ladeanimation rendern werde, die sehr kompliziert ist, wenn sie noch geladen wird. Daher kann ich sowieso nicht einfach warten, denn wenn ich immer warte, wird render() jedes Mal mit dem nicht geladenen Code aufgerufen und die gesamte Ladeanimation erstellt, auch wenn sie bereits fertig ist.

    – SCLeo

    11. Juni 2017 um 15:58 Uhr

Benutzer-Avatar
Ausleger

Haftungsausschluss: Keine gute Antwort auf aktualisiertes OP, gilt pro Bibliothek und funktioniert nicht über Bereiche hinweg. Prüfen Auf .then stattdessen.

Diese Antwort, basierend auf der Spezifikation ist eine Möglichkeit, ein Versprechen zu testen, das nur manchmal funktioniert, zu Ihrer Information.

Promise.resolve(obj) == obj &&
BLUEBIRD.resolve(obj) == obj

Wenn dies funktioniert, liegt es daran, dass die Algorithmus fordert das ausdrücklich Promise.resolve muss genau das übergebene Objekt zurückgeben, wenn und nur wenn es ist ein Versprechen, das von diesem Konstruktor erstellt wurde.

  • solltest du verwenden === Anstatt von ==?

    – Neil S

    3. August 2016 um 19:29 Uhr

  • @NeilS == ist gut.

    – Fock

    3. August 2016 um 19:47 Uhr


  • Dies wird auch bei Versprechen scheitern, die nicht aus demselben Bereich stammen.

    – Benjamin Grünbaum

    24. August 2016 um 19:54 Uhr

  • “Ein Versprechen durch die Definition der Spezifikation” scheint “ein Versprechen, das von demselben Konstruktor erstellt wurde wie ein Versprechen, das durch Promise.resolve() erstellt wurde” zu bedeuten – daher wird dies nicht erkannt, wenn z. ein polyfilled Promise ist eigentlich ein Promise

    – VoxPelli

    25. November 2016 um 15:12 Uhr

  • Diese Antwort könnte verbessert werden, wenn sie zunächst angibt, wie Sie die Frage interpretieren, anstatt sofort mit einer Antwort zu beginnen – das OP hat es leider überhaupt nicht klar gemacht, und Sie haben es an dieser Stelle auch nicht Das OP, der Autor und der Leser befinden sich wahrscheinlich auf 3 verschiedenen Seiten. Das Dokument, auf das Sie sich beziehen, sagt: „Wenn das Argument ein Versprechen ist von diesem Konstrukteur produziert“, wobei der kursiv geschriebene Teil entscheidend ist. Es wäre gut zu sagen, dass dies die Frage ist, die Sie beantworten. Außerdem ist Ihre Antwort für einen Benutzer dieser Bibliothek nützlich, aber nicht für den Implementierer.

    – Don Hatch

    14. Dezember 2016 um 23:21 Uhr


Benutzer-Avatar
Ausleger

Haftungsausschluss: Keine gute Antwort auf aktualisiertes OP, funktioniert nur für native und nicht über Realms hinweg. Folgen Sie stattdessen der akzeptierten Antwort.

obj instanceof Promise

Sollte es tun. Beachten Sie, dass dies möglicherweise nur mit nativen es6-Versprechen zuverlässig funktioniert.

Wenn Sie ein Shim, eine Promise-Bibliothek oder irgendetwas anderes verwenden, das vorgibt, Promise-like zu sein, dann ist es möglicherweise angemessener, auf ein “thenable” (alles mit a .then Methode), wie in anderen Antworten hier gezeigt.

Benutzer-Avatar
unobf

if (typeof thing?.then === 'function') {
    // probably a promise
} else {
    // definitely not a promise
}

  • Was ist, wenn das Ding undefiniert ist? Dagegen müssen Sie sich mit dem Ding && wehren …

    – HerrBorna

    2. Dezember 2017 um 14:33 Uhr

  • nicht optimal, aber definitiv sehr wahrscheinlich; hängt auch vom Umfang des Problems ab. 100 % defensiv zu schreiben ist normalerweise in offenen öffentlichen APIs anwendbar oder wenn Sie wissen, dass die Form/Signatur von Daten vollständig offen ist.

    – rob2d

    1. Mai 2018 um 5:10 Uhr


  • @mrBorna Die ? in thing?.then behandelt die undefinierte Prüfung. Dies wird als “optionale Verkettung” bezeichnet. Weiterlesen: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

    – Ajay

    15. Januar 2021 um 11:03 Uhr

  • if (p && 'then' in p && typeof p.then === 'function')

    – Jonathan

    5. Oktober 2021 um 8:24 Uhr

  • Die Antwort beantwortet tatsächlich die Frage, anstatt zu anderen Anleitungen abzulenken. Vielen Dank!

    – elektrovir

    1. Mai um 15:06 Uhr

Um zu sehen, ob das gegebene Objekt a ist ES6-Versprechenkönnen wir dieses Prädikat verwenden:

function isPromise(p) {
  return p && Object.prototype.toString.call(p) === "[object Promise]";
}

Calling toString direkt von der Object.prototype gibt a zurück native Zeichenfolgendarstellung des gegebenen Objekttyps, der ist "[object Promise]" in unserem Fall. Dadurch wird sichergestellt, dass das angegebene Objekt

  • Umgeht Fehlalarme wie..:
    • Selbstdefinierter Objekttyp mit gleichem Konstruktornamen (“Promise”).
    • Selbst geschrieben toString Methode des angegebenen Objekts.
  • Funktioniert in mehreren Umgebungskontexten (z. B. iframes) im Kontrast zu instanceof oder isPrototypeOf.

Allerdings keine besondere Host-Objektdas hat seine Tag geändert über Symbol.toStringTagkann zurückkehren "[object Promise]". Dies kann je nach Projekt das beabsichtigte Ergebnis sein oder nicht (z. B. wenn es eine benutzerdefinierte Promise-Implementierung gibt).


Um zu sehen, ob das Objekt von a natives ES6-Versprechenwir können benutzen:

function isNativePromise(p) {
  return p && typeof p.constructor === "function"
    && Function.prototype.toString.call(p.constructor).replace(/\(.*\)/, "()")
    === Function.prototype.toString.call(/*native object*/Function)
      .replace("Function", "Promise") // replacing Identifier
      .replace(/\(.*\)/, "()"); // removing possible FormalParameterList 
}

Entsprechend Dies und diese Abteilung der Spezifikation sollte die Zeichenfolgendarstellung der Funktion wie folgt aussehen:

“Funktion Kennung ( FormaleParameterlisteopt ) { FunctionBody }”

was oben entsprechend gehandhabt wird. Das FunctionBody ist [native code] in allen gängigen Browsern.

MDN: Function.prototype.toString

Dies funktioniert auch über mehrere Umgebungskontexte hinweg.

  • Was ist, wenn das Ding undefiniert ist? Dagegen müssen Sie sich mit dem Ding && wehren …

    – HerrBorna

    2. Dezember 2017 um 14:33 Uhr

  • nicht optimal, aber definitiv sehr wahrscheinlich; hängt auch vom Umfang des Problems ab. 100 % defensiv zu schreiben ist normalerweise in offenen öffentlichen APIs anwendbar oder wenn Sie wissen, dass die Form/Signatur von Daten vollständig offen ist.

    – rob2d

    1. Mai 2018 um 5:10 Uhr


  • @mrBorna Die ? in thing?.then behandelt die undefinierte Prüfung. Dies wird als “optionale Verkettung” bezeichnet. Weiterlesen: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

    – Ajay

    15. Januar 2021 um 11:03 Uhr

  • if (p && 'then' in p && typeof p.then === 'function')

    – Jonathan

    5. Oktober 2021 um 8:24 Uhr

  • Die Antwort beantwortet tatsächlich die Frage, anstatt zu anderen Anleitungen abzulenken. Vielen Dank!

    – elektrovir

    1. Mai um 15:06 Uhr

Benutzer-Avatar
muratgözel

Das ist wie graphql-js Paket erkennt Versprechungen:

function isPromise(value) {
  return Boolean(value && typeof value.then === 'function');
}

value ist der zurückgegebene Wert Ihrer Funktion. Ich verwende diesen Code in meinem Projekt und habe bisher kein Problem.

1318770cookie-checkWie überprüfe ich, ob ein Objekt ein Promise ist?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy