javascript - promesas - innerhtml
¿Cómo puedo saber si un objeto es una promesa? (14)
Cómo decide una biblioteca de promesas
Si tiene una función
.then
, esa es la
única
promesa estándar que usan las bibliotecas.
La especificación Promises / A + tiene una noción llamada
then
capaz que es básicamente "un objeto con un método de
then
".
Las promesas deben y deben 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 specification :
2.3.3.3 si
then
es una función, llámela con x como esto, primer argumento resolvePromise y segundo argumento acceptPromise
También explica la justificación de esta decisión de diseño:
Este tratamiento de ables permite que las implementaciones de promesas interoperen, siempre que expongan un método de Promesas / A + que cumpla
then
. También permite que las implementaciones de Promises / A + "asimilen" implementaciones no conformes con métodos razonables.
Cómo debes decidir
No debería, en su lugar, llamar a
Promise.resolve(x)
(
Q(x)
en Q) que
siempre
convertirá cualquier valor o externo que pueda convertirse 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
Ya sea una promesa ES6 o una promesa Bluebird, Q Promise, etc.
¿Cómo pruebo para ver si un objeto dado es una promesa?
Aquí está el formulario de código https://github.com/ssnau/xkit/blob/master/util/is-promise.js
!!obj && (typeof obj === ''object'' || typeof obj === ''function'') && typeof obj.then === ''function'';
si un objeto con un método
then
, debe tratarse como una
Promise
.
Aquí está mi respuesta original, que desde entonces ha sido ratificada en la especificación como la forma de probar una promesa:
Promise.resolve(obj) == obj
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 sentía 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.
Así es como el paquete graphql-js detecta promesas:
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));
});
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.
Comprobar si algo es prometedor complica innecesariamente el código, solo use
Promise.resolve
Promise.resolve(valueOrPromiseItDoesntMatter).then(function(value) {
})
Después de buscar una forma confiable de detectar funciones asincrónicas o incluso promesas , terminé usando la siguiente prueba:
() => fn.constructor.name === ''Promise'' || fn.constructor.name === ''AsyncFunction''
ES6:
const promise = new Promise(resolve => resolve(''olá''));
console.log(promise.toString().includes(''Promise'')); //true
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 devuelve
x is Promise<any>
y no necesitará hacer typecasts.
A continuación, en mi ejemplo,
c
es una promesa o uno de mis tipos que quiero convertir en una promesa llamando al método
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;
}
Más información: https://www.typescriptlang.org/docs/handbook/advanced-types.html
No es una respuesta a la pregunta completa, pero creo que vale la pena mencionar que en Node.js 10 se agregó una nueva función de
isPromise
llamada
isPromise
que verifica si un objeto es una Promesa nativa o no:
const utilTypes = require(''util'').types
const b_Promise = require(''bluebird'')
utilTypes.isPromise(Promise.resolve(5)) // true
utilTypes.isPromise(b_Promise.resolve(5)) // false
Para ver si el objeto dado es una promesa ES6 , podemos hacer uso de este predicado:
function isPromise(p) {
return p && Object.prototype.toString.call(p) === "[object Promise]";
}
Call
a
toString
directamente desde el
Object.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 dado
-
Omite falsos positivos como ..:
- Tipo de objeto autodefinido con el mismo nombre de constructor ("Promesa").
-
Método de escritura automática
toString
del objeto dado.
-
Funciona en múltiples contextos de entorno (por ejemplo, iframes)
en contraste con
instanceof
oisPrototypeOf
.
Sin embargo, cualquier
objeto host
particular, que tenga su
etiqueta modificada a través de
Symbol.toStringTag
, puede devolver
"[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:
function isNativePromise(p) {
return p && typeof p.constructor === "function"
&& Function.prototype.toString.call(p.constructor).replace(//(.*/)/, "()")
=== Function.prototype.toString.call(/*native object*/Function)
.replace("Function", "Promise") // replacing Identifier
.replace(//(.*/)/, "()"); // removing possible FormalParameterList
}
De acuerdo con this y esta sección de la especificación, la representación de cadena de la función debe ser:
" Identificador de función ( FormalParameterList opt ) { FunctionBody }"
que se maneja en consecuencia arriba.
FunctionBody
es
[native code]
en todos los principales navegadores.
MDN:
Function.prototype.toString
Esto también funciona en múltiples contextos de entorno.
Si utiliza un método asíncrono, puede hacerlo y evitar cualquier ambigüedad.
async myMethod(promiseOrNot){
const theValue = await promiseOrNot()
}
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.
Actualización: esta ya no es la mejor respuesta. Por favor vote mi otra respuesta en su lugar.
obj instanceof Promise
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 probar un "thenable" (cualquier cosa con un método
.then
), como se muestra en otras respuestas aquí.
function isPromise(value) {
return Boolean(value && typeof value.then === ''function'');
}
if (typeof thing.then === ''function'') {
// probably a promise
} else {
// definitely not a promise
}