Qu'il s'agisse d'une promesse ES6 ou d'une promesse bluebird, d'une promesse Q, etc.
Comment puis-je tester pour voir si un objet donné est une promesse?
javascript
promise
q
bluebird
es6-promise
le bélier
la source
la source
.then
méthode, mais cela ne vous dirait pas que ce que vous avez est définitivement une promesse. Tout ce que vous savez à ce stade, c'est que vous avez quelque chose qui expose une.then
méthode, comme une promesse..then
méthode qui n'est pas une promesse, ne se comporte pas comme une promesse et n'avait aucune intention d'être utilisée comme une promesse. Vérification d'une.then
méthode vous indique juste que le si l' objet n'a pas avoir une.then
méthode, vous n'avez une promesse. L'inverse - que l'existence d'un moyen de la méthode que vous faites ont une promesse - n'est pas nécessairement vrai..then
.then
méthode. Oui, cela a le potentiel de faux positifs, mais c'est l'hypothèse sur laquelle toutes les bibliothèques de promesses comptent (car c'est tout ce sur quoi elles peuvent compter). La seule alternative pour autant que je puisse voir est de prendre la suggestion de Benjamin Gruenbaum et de l'exécuter dans la suite de tests promesse. Mais ce n'est pas pratique pour le code de production réel.Réponses:
Comment une bibliothèque de promesses décide
S'il a une
.then
fonction - c'est la seule promesse standard que les bibliothèques utilisent.La spécification Promises / A + a une notion appelée
then
capable qui est fondamentalement "un objet avec unethen
méthode". Les promesses assimileront et devraient assimiler n'importe quoi avec une méthode alors. Toutes les mises en œuvre de promesses que vous avez mentionnées le font.Si nous regardons la spécification :
Il explique également la justification de cette décision de conception:
Comment vous devez décider
Vous ne devriez pas - à la place appeler
Promise.resolve(x)
(Q(x)
en Q) qui convertira toujours n'importe quelle valeur ou externethen
en une promesse de confiance. C'est plus sûr et plus facile que d'effectuer ces vérifications vous-même.vraiment besoin d'être sûr?
Vous pouvez toujours l'exécuter via la suite de tests : D
la source
Vérifier si quelque chose est promis complique inutilement le code, utilisez simplement
Promise.resolve
la source
Voici ma réponse originale, qui a depuis été ratifiée dans la spécification comme moyen de tester une promesse:
Cela fonctionne parce que l' algorithme demande explicitement que
Promise.resolve
doit renvoyer l'objet exact transmis si et seulement si c'est une promesse par la définition de la spécification.J'ai une autre réponse ici, qui disait cela, mais je l'ai changé pour autre chose quand cela ne fonctionnait pas avec Safari à l'é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 d'origine, sauf que cela ne me semblait pas correct, étant donné que plus de personnes ont maintenant voté pour la solution modifiée dans cette réponse que l'original. Je pense que c'est la meilleure réponse, et j'espère que vous êtes d'accord.
la source
===
place de==
?Mise à jour: ce n'est plus la meilleure réponse. Veuillez voter mon autre réponse à la place.
devrait le faire. Notez que cela ne peut fonctionner de manière fiable qu'avec les promesses natives d'es6.
Si vous utilisez une cale, une bibliothèque de promesses ou tout autre élément faisant semblant de ressembler à une promesse, il peut être plus approprié de tester un élément "utilisable" (tout ce qui a une
.then
méthode), comme indiqué dans d'autres réponses ici.la source
Promise.resolve(obj) == obj
ne fonctionnera pas dans Safari. Utilisezinstanceof Promise
plutôt.obj && typeof obj.then == 'function'
place, car cela fonctionnera avec tous les types de promesses et est en fait la manière recommandée par la spécification et utilisée par les implémentations / polyfills. NativePromise.all
par exemple fonctionnera sur toutes lesthen
capacités, pas seulement sur d'autres promesses natives. Il en va de même pour votre code. Ceinstanceof Promise
n'est donc pas une bonne solution.console.log(typeof p, p, p instanceof Promise);
produit cette sortie:object Promise { <pending> } false
. Comme vous pouvez le voir, c'est une promesse, et pourtant leinstanceof Promise
test revientfalse
?la source
Pour voir si l'objet donné est une promesse ES6 , nous pouvons utiliser ce prédicat:
Call
ingtoString
directement à partir duObject.prototype
retourne une représentation sous forme de chaîne native du type d'objet donné, ce qui est"[object Promise]"
dans notre cas. Cela garantit que l'objet donnétoString
Méthode auto-écrite de l'objet donné.instanceof
ouisPrototypeOf
.Cependant, tout objet hôte particulier , dont la balise est modifiée via
Symbol.toStringTag
, peut retourner"[object Promise]"
. Cela peut être le résultat souhaité ou non selon le projet (par exemple, s'il existe une implémentation Promise personnalisée).Pour voir si l'objet provient d'une promesse ES6 native , nous pouvons utiliser:
Selon ceci et cette section de la spécification, la représentation sous forme de chaîne de la fonction devrait être:
qui est traité en conséquence ci-dessus. Le FunctionBody est
[native code]
dans tous les principaux navigateurs.MDN:
Function.prototype.toString
Cela fonctionne également dans plusieurs contextes d'environnement.
la source
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 appelée a
isPromise
été ajoutée qui vérifie si un objet est une promesse native ou non:la source
Voici comment le package graphql-js détecte les promesses:
value
est la valeur retournée de votre fonction. J'utilise ce code dans mon projet et je n'ai aucun problème jusqu'à présent.la source
Voici la forme de code https://github.com/ssnau/xkit/blob/master/util/is-promise.js
si un objet avec une
then
méthode, il doit être traité comme unPromise
.la source
Dans le cas où vous utilisez Typescript , je voudrais ajouter que vous pouvez utiliser la fonction "type prédicat". Il suffit d'envelopper la vérification logique dans une fonction qui revient
x is Promise<any>
et vous n'aurez pas besoin de faire de typecasts. Ci-dessous sur mon exemple,c
est soit une promesse ou l'un de mes types que je veux convertir en promesse en appelant lac.fetch()
méthode.Plus d'informations: https://www.typescriptlang.org/docs/handbook/advanced-types.html
la source
Si vous utilisez une méthode asynchrone, vous pouvez le faire et éviter toute ambiguïté.
Si la fonction renvoie promesse, elle attendra et reviendra avec la valeur résolue. Si la fonction renvoie une valeur, elle sera traitée comme résolue.
Si la fonction ne renvoie pas de promesse aujourd'hui, mais que demain en retourne une ou est déclarée asynchrone, vous serez à l'épreuve du temps.
la source
Promise.resolve()
la source
J'utilise cette fonction comme une solution universelle:
la source
après avoir cherché un moyen fiable de détecter les fonctions asynchrones ou même les promesses , j'ai fini par utiliser le test suivant:
la source
Promise
- classe et créez des instances de cela, ce test peut échouer. cela devrait cependant fonctionner pour la plupart de ce que vous essayez de tester.fn.constructor.name === 'AsyncFunction'
est faux - cela signifie que quelque chose est une fonction asynchrone et non une promesse - il n'est pas non plus garanti de fonctionner parce que les gens peuvent sousES6:
la source
toString
méthode peut simplement renvoyer une chaîne qui inclut"Promise"
.'NotAPromise'.toString().includes('Promise') === true