Ya sea una promesa ES6 o una promesa Bluebird, Q Promise, etc.
¿Cómo pruebo para ver si un objeto dado es una promesa?
javascript
promise
q
bluebird
es6-promise
el carnero
fuente
fuente
.then
método, pero eso no le diría que lo que tiene es una Promesa definitivamente. Todo lo que sabría en ese momento es que tiene algo que expone un.then
método, como una Promesa..then
método que no sea una Promesa, no se comporte como una Promesa y no tuviera la intención de ser utilizado como una Promesa. Buscar un.then
método solo te dice que si el objeto no tiene un.then
método, entonces no tienes una Promesa. La inversa - que la existencia de unos.then
medios método que haces tiene una promesa - no es necesariamente cierto..then
método. Sí, eso tiene el potencial de falsos positivos, pero se supone que todas las bibliotecas prometedoras dependen (porque eso es todo en lo que pueden confiar). La única alternativa hasta donde puedo ver es tomar la sugerencia de Benjamin Gruenbaum y ejecutarla a través del conjunto de pruebas de promesa. Pero eso no es práctico para el código de producción real.Respuestas:
Cómo decide una biblioteca de promesas
Si tiene una
.then
función, esa es la única promesa estándar que usan las bibliotecas.La especificación Promesas / A + tiene una noción llamada
then
capaz que es básicamente "un objeto con unthen
método". Las promesas harán y deberían asimilar cualquier cosa con un método de entonces. Toda la implementación de promesa que ha mencionado hace esto.Si nos fijamos en la especificación :
También explica la justificación de esta decisión de diseño:
Cómo deberías decidir
No debería, en su lugar, llamar
Promise.resolve(x)
(Q(x)
en Q) que siempre convertirá cualquier valor othen
capacidad externa en una promesa confiable. Es más seguro y fácil que realizar estas comprobaciones usted mismo.realmente necesita estar seguro?
Siempre puede ejecutarlo a través del conjunto de pruebas : D
fuente
Comprobar si algo es prometedor complica innecesariamente el código, solo use
Promise.resolve
fuente
Aquí está mi respuesta original, que desde entonces ha sido ratificada en la especificación como la forma de probar una promesa:
Esto funciona porque el algoritmo exige explícitamente que
Promise.resolve
debe devolver el objeto exacto pasado si y solo si es una promesa según la definición de la especificación.Tengo otra respuesta aquí, que solía decir esto, pero la cambié a otra cuando no funcionaba con Safari en ese momento. Eso fue hace un año, y ahora funciona de manera confiable incluso en Safari.
Habría editado mi respuesta original, excepto que se sintió mal, dado que ahora más personas han votado por la solución alterada en esa respuesta que la original. Creo que esta es la mejor respuesta, y espero que esté de acuerdo.
fuente
===
lugar de==
?Actualización: esta ya no es la mejor respuesta. Por favor vote mi otra respuesta en su lugar.
Deberías hacerlo. Tenga en cuenta que esto solo puede funcionar de manera confiable con las promesas nativas de es6.
Si está utilizando una cuña, una biblioteca de promesas o cualquier otra cosa que pretenda ser como una promesa, entonces puede ser más apropiado hacer una prueba para un "thenable" (cualquier cosa con un
.then
método), como se muestra en otras respuestas aquí.fuente
Promise.resolve(obj) == obj
no funcionará en Safari. Usar en suinstanceof Promise
lugar.obj && typeof obj.then == 'function'
, porque funcionará con todo tipo de promesas y en realidad es la forma recomendada por la especificación y utilizada por las implementaciones / polyfills. Native,Promise.all
por ejemplo, funcionará en todas lasthen
capacidades, no solo en otras promesas nativas. También debería tu código. Entoncesinstanceof Promise
no es una buena solución.console.log(typeof p, p, p instanceof Promise);
produce este resultado:object Promise { <pending> } false
. Como puede ver, es una promesa, ¿y lainstanceof Promise
prueba vuelvefalse
?fuente
Para ver si el objeto dado es una promesa ES6 , podemos hacer uso de este predicado:
Call
ingtoString
directamente delObject.prototype
devuelve una representación de cadena nativa del tipo de objeto dado que es"[object Promise]"
en nuestro caso. Esto asegura que el objeto dadotoString
Método auto-escrito del objeto dado.instanceof
oisPrototypeOf
.Sin embargo, cualquier objeto host particular , que tenga su etiqueta modificada a través de
Symbol.toStringTag
, puede regresar"[object Promise]"
. Este puede ser el resultado deseado o no dependiendo del proyecto (por ejemplo, si hay una implementación personalizada de Promise).Para ver si el objeto es de una Promesa ES6 nativa , podemos usar:
De acuerdo con esta y esta sección de la especificación, la representación de cadena de la función debe ser:
que se maneja en consecuencia arriba. El FunctionBody es
[native code]
en todos los principales navegadores.MDN:
Function.prototype.toString
Esto también funciona en múltiples contextos de entorno.
fuente
No es una respuesta a la pregunta completa, pero creo que vale la pena mencionar que en Node.js 10
isPromise
se agregó una nueva función de utilidad llamada que comprueba si un objeto es una Promesa nativa o no:fuente
Así es como el paquete graphql-js detecta las promesas:
value
es el valor devuelto de su función. Estoy usando este código en mi proyecto y no tengo ningún problema hasta ahora.fuente
Aquí está el formulario de código https://github.com/ssnau/xkit/blob/master/util/is-promise.js
si un objeto con un
then
método, debe tratarse como aPromise
.fuente
En caso de que esté utilizando Typecript , me gustaría agregar que puede usar la función "predicado de tipo". Solo debe envolver la verificación lógica en una función que regrese
x is Promise<any>
y no necesitará hacer typecasts. A continuación, en mi ejemplo,c
hay una promesa o uno de mis tipos que quiero convertir en una promesa llamando alc.fetch()
método.Más información: https://www.typescriptlang.org/docs/handbook/advanced-types.html
fuente
Si utiliza un método asíncrono, puede hacerlo y evitar cualquier ambigüedad.
Si la función devuelve la promesa, esperará y volverá con el valor resuelto. Si la función devuelve un valor, se tratará como resuelto.
Si la función no devuelve una promesa hoy, pero mañana devuelve una o se declara asíncrona, estará preparado para el futuro.
fuente
Promise.resolve()
fuente
Yo uso esta función como una solución universal:
fuente
Después de buscar una forma confiable de detectar funciones asincrónicas o incluso promesas , terminé usando la siguiente prueba:
fuente
Promise
y crea instancias de eso, esta prueba puede fallar. Sin embargo, esto debería funcionar para la mayoría de lo que estás tratando de probar.fn.constructor.name === 'AsyncFunction'
está mal, significa que algo es una función asincrónica y no una promesa, tampoco se garantiza que funcione porque la gente puede subclasificar las promesasES6:
fuente
toString
método puede devolver una cadena que incluya"Promise"
.'NotAPromise'.toString().includes('Promise') === true