wake-up-neo.com

Wie kann ich feststellen, ob ein Objekt ein Versprechen ist

Sei es ein ES6-Versprechen oder ein Bluebird-Versprechen, Q-Versprechen usw.

Wie teste ich, ob ein Objekt ein Versprechen ist?

245
theram

Wie eine Versprechenbibliothek entscheidet

Wenn es eine .then-Funktion hat, ist dies die Standardversprechenbibliothek von only

Die Promises/A + -Spezifikation hat einen Begriff namens thenable, der im Wesentlichen "ein Objekt mit einer then-Methode" ist. Versprechen werden und sollten irgendetwas mit einer dann-Methode assimilieren. Alle versprochenen Implementierungen, die Sie erwähnt haben, tun dies.

Wenn wir uns die Spezifikation ansehen :

2.3.3.3 Wenn then eine Funktion ist, rufen Sie sie mit x als diesem, dem ersten Argument resolPromise und dem zweiten Argument rejectPromise auf

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

Diese Behandlung von thenables ermöglicht versprechende Implementierungen zur Interoperabilität, sofern sie eine Promises/A + -konforme then-Methode verfügbar machen. Promises/A + -Implementierungen können auch nichtkonforme Implementierungen mit vernünftigen Methoden "assimiliert" werden.

Wie solltest du entscheiden?

Sie sollten nicht - stattdessen Promise.resolve(x) (Q(x) in Q) aufrufen, um always jeden Wert oder eine externe thenable in ein vertrauenswürdiges Versprechen umzuwandeln. Es ist sicherer und einfacher, als diese Prüfungen selbst durchzuführen. 

wirklich müssen sicher sein?

Sie können es immer durch die Testsuite : D ausführen

245

Die Überprüfung, ob ein Versprechen unnötig ist, macht den Code unnötig kompliziert. Verwenden Sie einfach Promise.resolve.

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

})
122
Esailija

Hier ist meine ursprüngliche Antwort, die seitdem in der Spezifikation ratifiziert ist, um ein Versprechen zu erhalten:

Promise.resolve(obj) == obj

Dies funktioniert, weil der Algorithmus explizit verlangt, dass Promise.resolve genau das übergebene Objekt zurückgibt, wenn und nur dann, wenn durch die Definition der Spezifikation ein Versprechen ist.

Ich habe hier eine andere Antwort, die das immer gesagt hat, aber ich habe sie in etwas anderes geändert, als es zu dieser Zeit nicht mit Safari funktionierte. Das war vor einem Jahr, und das funktioniert jetzt auch in Safari zuverlässig.

Ich hätte meine ursprüngliche Antwort bearbeitet, mit der Ausnahme, dass dies falsch war, da inzwischen mehr Menschen für die geänderte Lösung gestimmt haben als das Original. Ich glaube, das ist die bessere Antwort, und ich hoffe, Sie stimmen zu.

66
jib

Update: Dies ist nicht mehr die beste Antwort. Bitte wählen Sie stattdessen meine andere 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 Versprechungsbibliothek oder etwas anderes verwenden, das vorgibt, versprechend zu sein, kann es sinnvoller sein, auf "Thenable" (alles mit einer .then-Methode) zu testen, wie in den anderen Antworten hier gezeigt.

42
jib
if (typeof thing.then === 'function') {
    // probably a promise
} else {
    // definitely not a promise
}
39
unobf

Um zu sehen, ob das angegebene Objekt ein native ES6 Promise ist, können wir dieses Prädikat verwenden:

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

Call ing toString direkt aus Object.prototype gibt eine native Stringdarstellung zurück des angegebenen Objekttyps, die in unserem Fall "[object Promise]" ist. Dies stellt sicher, dass das angegebene Objekt

  • Umgeht falsch positive Ergebnisse wie ..:
    • Selbstdefinierter Objekttyp mit demselben Konstruktornamen ("Promise").
    • Selbstgeschriebene toString-Methode des angegebenen Objekts.
  • Funktioniert in mehreren Umgebungskontexten (z. B. iframes) im Gegensatz zu instanceof oder isPrototypeOf.
12

Hier ist das Code-Formular https://github.com/ssnau/xkit/blob/master/util/is-promise.js

!!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';

wenn ein Objekt eine then-Methode hat, sollte es als Promise behandelt werden.

6
ssnau

Falls Sie TypeScript verwenden, möchte ich hinzufügen, dass Sie die Funktion "Typ Prädikat" verwenden können. Sie sollten nur die logische Überprüfung in eine Funktion einschließen, die x is Promise<any> zurückgibt, und Sie müssen keine Typumwandlungen durchführen. Unten in meinem Beispiel ist c entweder ein Versprechen oder einer meiner Typen, die ich durch Aufruf der c.fetch()-Methode in ein Versprechen umwandeln möchte.

export function toPromise(c: Container<any> | Promise<any>): Promise<any> {
    if (c == null) return Promise.resolve();
    return isContainer(c) ? c.fetch() : c;
}

export function isContainer(val: Container<any> | Promise<any>): val is Container<any> {
    return val && (<Container<any>>val).fetch !== undefined;
}

export function isPromise(val: Container<any> | Promise<any>): val is Promise<any> {
    return val && (<Promise<any>>val).then !== undefined;
}

Weitere Informationen: https://www.typescriptlang.org/docs/handbook/advanced-types.html

4
Murilo Perrone

Wenn Sie sich in einer asynchronen Methode befinden, können Sie dies tun und Mehrdeutigkeiten vermeiden.

async myMethod(promiseOrNot){
  const theValue = await promiseOrNot()
}

Wenn die Funktion ein Versprechen zurückgibt, wird sie den aufgelösten Wert abwarten und zurückgeben. Wenn die Funktion einen Wert zurückgibt, wird dieser als aufgelöst behandelt.

Wenn die Funktion heute kein Versprechen zurückgibt, morgen jedoch eines zurückgibt oder für asynchron erklärt wird, sind Sie zukunftssicher.

3
Steven Spungin
it('should return a promise', function() {
    var result = testedFunctionThatReturnsPromise();
    expect(result).toBeDefined();
    // 3 slightly different ways of verifying a promise
    expect(typeof result.then).toBe('function');
    expect(result instanceof Promise).toBe(true);
    expect(result).toBe(Promise.resolve(result));
});
2
purplecabbage

Keine Antwort auf die gesamte Frage, aber ich denke, es ist erwähnenswert, dass in Node.js 10 eine neue util-Funktion namens isPromise hinzugefügt wurde, die prüft, ob ein Objekt ein natives Promise ist oder nicht:

const utilTypes = require('util').types
const b_Promise = require('bluebird')

utilTypes.isPromise(Promise.resolve(5)) // true
utilTypes.isPromise(b_Promise.resolve(5)) // false
1
LEQADA

So erkennt graphql-js package Versprechen:

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

value ist der Rückgabewert Ihrer Funktion. Ich verwende diesen Code in meinem Projekt und habe bisher kein Problem.

0
muratgozel