Ob es sich um ein ES6-Versprechen oder ein Bluebird-Versprechen, ein Q-Versprechen usw. handelt.
Wie teste ich, ob ein bestimmtes Objekt ein Versprechen ist?
javascript
promise
q
bluebird
es6-promise
Theram
quelle
quelle
.then
Methode suchen, 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 eine.then
Methode enthüllt , wie ein Versprechen..then
Methode verfügbar macht, die kein Versprechen ist, sich nicht wie ein Versprechen verhält und nicht die Absicht hatte, wie ein Versprechen verwendet zu werden. Überprüfen auf eine.then
Methode sagt Ihnen , nur , dass das , wenn das Objekt nicht eine hat.then
Methode, dann sind Sie nicht haben ein Versprechen. Die inverse - , dass die Existenz eines.then
Verfahrens bedeutet , dass Sie tun , ein Versprechen haben - ist nicht unbedingt wahr..then
Methode gibt. Ja, das kann zu Fehlalarmen führen, aber es wird davon ausgegangen, dass sich alle Versprechen-Bibliotheken darauf verlassen (denn darauf können sie sich nur verlassen). Die einzige Alternative, soweit ich sehen kann, besteht darin, den Vorschlag von Benjamin Gruenbaum anzunehmen und ihn durch die Versprechens-Testsuite zu führen. Für den tatsächlichen Produktionscode ist dies jedoch nicht praktikabel.Antworten:
Wie eine Versprechensbibliothek entscheidet
Wenn es eine
.then
Funktion hat, ist dies die einzige Standardversprechen-Bibliothek, die verwendet wird.Die Promises / A + -Spezifikation hat einen Begriff namens
then
able, der im Grunde "ein Objekt mit einerthen
Methode" ist. Versprechen werden und sollten alles mit einer Dann-Methode aufnehmen. Alle von Ihnen erwähnten Versprechen-Implementierungen tun dies.Wenn wir uns die Spezifikation ansehen :
Außerdem werden die Gründe für diese Entwurfsentscheidung erläutert:
Wie solltest du dich entscheiden?
Sie sollten nicht - stattdessen nennen
Promise.resolve(x)
(Q(x)
in Q) , die wird immer einen beliebigen Wert oder externe umwandelnthen
können in einer vertrauenswürdigen Versprechen. Es ist sicherer und einfacher, als diese Überprüfungen selbst durchzuführen.Müssen Sie wirklich sicher sein?
Sie können es jederzeit über die Testsuite ausführen : D.
quelle
Promise.resolve
sagen Sie nichts und konvertieren dabei Objekte. Die Antwort wäre also (mit einem Objekt namenssubject
):var isPromise = typeof subject.then == 'function';
then
Methode, aber allethen
Methoden gehören nicht zu aPromise
. Ihre Aussage ist daher ungültig und beantwortet daher die Frage nicht.then
Methode , dann wird es als ein Versprechen behandelt und rekursiv durch assimiliert werden sollPromise.prototype.then
,Promise.resolve
all
race
oder derfulfill
Parameter des Versprechen Konstruktor. Sie können also technisch anders prüfen, aber die Sprache selbst prüft häufig und sie prüft so. Ich bin mir nicht sicher, was Ihre Ablehnung bedeutet oder was daran falsch ist, da der Abschnitt, den Sie kommentieren, mit "Wie eine Versprechensbibliothek entscheidet" beginnt und das ist richtigWenn Sie überprüfen, ob etwas versprochen wird, wird der Code unnötig kompliziert. Verwenden Sie einfach
Promise.resolve
quelle
Hier ist meine ursprüngliche Antwort, die seitdem in der Spezifikation als Test für ein Versprechen bestätigt wurde:
Dies funktioniert, weil der Algorithmus explizit verlangt, dass
Promise.resolve
das genaue übergebene Objekt genau dann zurückgegeben werden muss, wenn es nach der Definition der Spezifikation ein Versprechen ist.Ich habe hier eine andere Antwort, die dies früher sagte, aber ich habe sie in etwas anderes geändert, als es zu diesem Zeitpunkt mit Safari nicht funktionierte. Das war vor einem Jahr und das funktioniert jetzt auch in Safari zuverlässig.
Ich hätte meine ursprüngliche Antwort bearbeitet, außer das fühlte sich falsch an, da inzwischen mehr Menschen für die geänderte Lösung in dieser Antwort gestimmt haben als für das Original. Ich glaube, das ist die bessere Antwort, und ich hoffe, Sie stimmen zu.
quelle
===
anstelle von verwenden==
?Update: Dies ist nicht mehr die beste Antwort. Bitte stimmen Sie stattdessen meine andere Antwort ab .
Sollte es tun. Beachten Sie, dass dies möglicherweise nur mit nativen es6-Versprechungen zuverlässig funktioniert.
Wenn Sie eine Unterlegscheibe, eine Versprechensbibliothek oder etwas anderes verwenden, das vorgibt, wie ein Versprechen zu sein, ist es möglicherweise besser, auf ein "thenable" (alles mit einer
.then
Methode) zu testen , wie in anderen Antworten hier gezeigt.quelle
Promise.resolve(obj) == obj
nicht funktionieren in Safari. Verwenden Sieinstanceof Promise
stattdessen.obj && typeof obj.then == 'function'
stattdessen wirklich überprüfen , da es mit allen Arten von Versprechungen funktioniert und tatsächlich die von der Spezifikation empfohlene und von den Implementierungen / Polyfills verwendete Methode ist. EinheimischePromise.all
zum Beispiel funktionieren bei allenthen
Fähigkeiten, nicht nur bei anderen einheimischen Versprechungen. So sollte Ihr Code sein. Istinstanceof Promise
also keine gute Lösung.console.log(typeof p, p, p instanceof Promise);
diese Ausgabe erzeugt wird :object Promise { <pending> } false
. Wie Sie sehen, ist es ein Versprechen in Ordnung - und dochinstanceof Promise
kehrt der Test zurückfalse
?quelle
Um zu sehen, ob das angegebene Objekt ein ES6-Versprechen ist , können wir dieses Prädikat verwenden:
Call
ingtoString
direkt von denObject.prototype
Renditen einer nativen Stringdarstellung des Objekttypen gegeben , das ist"[object Promise]"
in unserem Fall. Dies stellt sicher, dass das gegebene ObjekttoString
Methode des gegebenen Objekts.instanceof
oderisPrototypeOf
.Jedes bestimmte Hostobjekt , dessen Tag über geändert wurde
Symbol.toStringTag
, kann jedoch zurückkehren"[object Promise]"
. Dies kann je nach Projekt das beabsichtigte Ergebnis sein oder auch nicht (z. B. wenn eine benutzerdefinierte Promise-Implementierung vorhanden ist).Um festzustellen, ob das Objekt aus einem nativen ES6-Versprechen stammt , können wir Folgendes verwenden:
Gemäß diesem und diesem Abschnitt der Spezifikation sollte die Zeichenfolgendarstellung der Funktion sein:
was oben entsprechend behandelt wird. Der FunctionBody befindet sich
[native code]
in allen gängigen Browsern.MDN:
Function.prototype.toString
Dies funktioniert auch in mehreren Umgebungskontexten.
quelle
Keine Antwort auf die vollständige Frage, aber ich denke, es ist erwähnenswert, dass in Node.js 10 eine neue Util-Funktion namens aufgerufen
isPromise
wurde, die prüft, ob ein Objekt ein natives Versprechen ist oder nicht:quelle
So erkennt das Paket graphql-js Versprechen:
value
ist der zurückgegebene Wert Ihrer Funktion. Ich verwende diesen Code in meinem Projekt und habe bisher kein Problem.quelle
Hier ist das Codeformular https://github.com/ssnau/xkit/blob/master/util/is-promise.js
Wenn ein Objekt mit einer
then
Methode, sollte es als behandelt werdenPromise
.quelle
Wenn Sie Typescript verwenden , möchte ich hinzufügen, dass Sie die Funktion "Typprädikat" verwenden können. Sie sollten nur die logische Überprüfung in eine Funktion einschließen, die zurückgibt,
x is Promise<any>
und Sie müssen keine Typecasts durchführen. Unten in meinem Beispielc
ist entweder ein Versprechen oder einer meiner Typen, die ich durch Aufrufen derc.fetch()
Methode in ein Versprechen umwandeln möchte .Weitere Informationen: https://www.typescriptlang.org/docs/handbook/advanced-types.html
quelle
Wenn Sie sich in einer asynchronen Methode befinden, können Sie dies tun und Unklarheiten vermeiden.
Wenn die Funktion Versprechen zurückgibt, wartet sie mit dem aufgelösten Wert und kehrt zurück. Wenn die Funktion einen Wert zurückgibt, wird dieser als aufgelöst behandelt.
Wenn die Funktion heute kein Versprechen zurückgibt, aber morgen eines zurückgibt oder als asynchron deklariert wird, sind Sie zukunftssicher.
quelle
Promise.resolve()
quelle
Ich benutze diese Funktion als universelle Lösung:
quelle
Nachdem ich nach einer zuverlässigen Methode gesucht hatte , um Async- Funktionen oder sogar Versprechen zu erkennen , verwendete ich den folgenden Test:
quelle
Promise
Instanzen davon unterordnen und erstellen, kann dieser Test fehlschlagen. Dies sollte jedoch für die meisten Dinge funktionieren, auf die Sie testen möchten.fn.constructor.name === 'AsyncFunction'
ist falsch - es bedeutet, dass etwas eine asynchrone Funktion und kein Versprechen ist - es ist auch nicht garantiert, dass es funktioniert, weil Leute VersprechenES6:
quelle
toString
Methode hat (oder überschrieben hat) , kann einfach eine Zeichenfolge zurückgeben, die enthält"Promise"
.'NotAPromise'.toString().includes('Promise') === true