Que ce soit une promesse ES6 ou une promesse bluebird, une promesse Q, etc.
Comment puis-je tester pour voir si un objet donné est une promesse?
Si elle a une fonction .then
, il s’agit de la bibliothèque de promesses utilisée par seulement.
La spécification Promises/A + a une notion appelée then
able qui est fondamentalement "un objet avec une méthode then
". Les promesses vont et devront assimiler n'importe quoi avec une méthode d'alors. Toute la mise en œuvre de la promesse que vous avez mentionnée le fait.
Si nous regardons la spécification :
2.3.3.3 si
then
est une fonction, appelez-la avec x comme ceci, le premier argument resolPromise et le second argument rejeterPromise
Il explique également la raison de cette décision de conception:
Ce traitement de
then
ables permet l’interopérabilité des implémentations de promesse, à condition qu’elles exposent une méthodethen
conforme à Promises/A +. Cela permet également aux implémentations de Promises/A + d'assimiler des implémentations non conformes avec des méthodes raisonnables.
Vous ne devriez pas - à la place appeler Promise.resolve(x)
(Q(x)
dans Q) qui always convertira toute valeur ou then
able externe en une promesse de confiance. Il est plus sûr et plus facile que d'effectuer ces vérifications vous-même.
Vous pouvez toujours l'exécuter via la suite de tests : D
Vérifier si quelque chose est promis complique inutilement le code, utilisez simplement Promise.resolve
Promise.resolve(valueOrPromiseItDoesntMatter).then(function(value) {
})
Voici ma réponse initiale, qui a depuis été ratifiée dans la spécification comme moyen de tester une promesse:
Promise.resolve(obj) == obj
Cela fonctionne parce que le algorithm exige explicitement que Promise.resolve
doit renvoyer l'objet exact transmis dans if et uniquement si c'est une promesse de la définition de la spéc.
J'ai une autre réponse ici, qui disait cela, mais je l'ai changée en autre chose quand cela ne fonctionnait pas avec Safari à cette époque. C'était il y a un an et cela fonctionne désormais de manière fiable, même dans Safari.
J'aurais modifié ma réponse initiale, sauf que je me sentais mal, étant donné que plus de personnes ont désormais voté pour la solution modifiée dans cette réponse par rapport à la réponse originale. Je crois que c'est la meilleure réponse et j'espère que vous êtes d'accord.
Mise à jour: Ce n'est plus la meilleure réponse. Veuillez voter mon autre réponse à la place.
obj instanceof Promise
devrait le faire. Notez que cela ne peut fonctionner de manière fiable qu'avec les promesses es6 natives.
Si vous utilisez un shim, une bibliothèque de promesses ou tout autre élément prétendant ressembler à une promesse, il peut être plus approprié de tester un "thenable" (tout avec une méthode .then
), comme indiqué dans d'autres réponses ici.
if (typeof thing.then === 'function') {
// probably a promise
} else {
// definitely not a promise
}
Pour voir si l'objet donné est une native ES6 Promise, nous pouvons utiliser ce prédicat:
function isPromise(value) {
return value && Object.prototype.toString.call(value) === "[object Promise]";
}
Call
ing toString
directement à partir du Object.prototype
renvoie une représentation de chaîne native du type d'objet donné qui est "[object Promise]"
dans notre cas. Cela garantit que l'objet donné
toString
auto-écrite de l'objet donné.instanceof
ou isPrototypeOf
.Voici le code/ https://github.com/ssnau/xkit/blob/master/util/is-promise.js
!!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';
si un objet avec une méthode then
, il doit être traité comme un Promise
.
Si vous utilisez TypeScript, j'aimerais ajouter que vous pouvez utiliser la fonctionnalité "type predicate". Vous devriez juste envelopper la vérification logique dans une fonction qui retourne x is Promise<any>
et vous n'aurez pas besoin de faire de dactylographie. Ci-dessous, dans mon exemple, c
est une promesse ou un de mes types que je souhaite convertir en une promesse en appelant la méthode c.fetch()
.
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;
}
Plus d'infos: https://www.typescriptlang.org/docs/handbook/advanced-types.html
Si vous utilisez une méthode asynchrone, vous pouvez le faire et éviter toute ambiguïté.
async myMethod(promiseOrNot){
const theValue = await promiseOrNot()
}
Si la fonction retourne promis, elle attendra et reviendra avec la valeur résolue. Si la fonction renvoie une valeur, celle-ci sera traitée comme résolue.
Si la fonction ne retourne pas une promesse aujourd'hui, mais si demain en renvoie une ou est déclarée asynchrone, vous serez à l'abri de l'avenir.
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));
});
Pas une réponse à la question complète mais je pense qu'il vaut la peine de mentionner que dans Node.js 10 une nouvelle fonction util nommée isPromise
a été ajoutée pour vérifier si un objet est une promesse native ou non:
const utilTypes = require('util').types
const b_Promise = require('bluebird')
utilTypes.isPromise(Promise.resolve(5)) // true
utilTypes.isPromise(b_Promise.resolve(5)) // false
Voici comment graphql-js package détecte les promesses:
function isPromise(value) {
return Boolean(value && typeof value.then === 'function');
}
value
est la valeur renvoyée de votre fonction. J'utilise ce code dans mon projet et je n'ai aucun problème jusqu'à présent.