recorrer que obtener objetos lista ejemplos div contenido carga asincrona array javascript jquery jquery-deferred

que - obtener contenido de un div javascript



¿Cómo puedo saber si un objeto es una promesa jQuery/diferida? (2)

Tengo una función que toma un solo argumento. Necesito poder saber si este argumento es un objeto jQuery Promise o Deferred . Si no, entonces el valor puede ser de cualquier tipo y tener propiedades, por lo que no es seguro solo por la presencia de los métodos de promesa.

Aquí hay un ejemplo de cómo me gustaría que se comportara mi función:

function displayMessage(message) { if (message is a Promise or Deferred) { message.then(displayMessage); } else { alert(message); } }

Observe el manejo recursivo de las promesas: si una promesa se resuelve con otro valor de promesa, no la mostramos, esperamos que se resuelva. Si vuelve otra promesa, repita.

Esto es importante porque si este no fuera el caso, solo podría usar jQuery.when :

function displayMessage(message) { jQuery.when(message).then(function(messageString) { alert(messageString); }); }

Esto manejaría valores y promesas de valores correctamente ...

displayMessage("hello"); // alerts "hello" displayMessage(jQuery.Deferred().resolve("hello")); // alerts "hello"

... pero una vez que llegamos a las promesas de promesas de valores, se rompe:

displayMessage(jQuery.Deferred().resolve( jQuery.Deferred().resolve("hello") )); // alerts "[object Object]"

jQuery.when es capaz de decir si un valor es una promesa, por lo que aparentemente es posible. ¿Cómo puedo comprobar?


jQuery.when es capaz de decir si un valor es una promesa, por lo que aparentemente es posible.

Esto es un error. jQuery en sí no puede comprobar si un objeto es una promesa con total precisión. Si observa la fuente de jQuery.when en el visor de fuente de jQuery puede ver que todo lo que hace es esto:

jQuery.isFunction(firstParam.promise)

Si el objeto que está devolviendo tiene su propio método .promise() , jQuery.when se comportará mal:

var trickyValue = { promise: function() { return 3; }, value: 2 }; jQuery.when(trickyValue).then(function(obj) { alert(obj.value); });

Esto .promise() TypeError: Object 3 has no method ''then'' , porque jQuery asume que el objeto es una promesa y confía en el valor de su método .promise() .

Esto es probablemente imposible de resolver adecuadamente. El objeto promesa se crea como un objeto literal dentro de jQuery.Deferred ( ver fuente ). No tiene ningún prototipo, ni ninguna otra propiedad verdaderamente única que pueda usarse para distinguirlo.

Sin embargo, puedo pensar en una solución hacky que debería ser confiable siempre y cuando solo se use una versión de jQuery:

function isPromise(value) { if (typeof value === ''object'' && typeof value.then !== "function") { return false; } var promiseThenSrc = String($.Deferred().then); var valueThenSrc = String(value.then); return promiseThenSrc === valueThenSrc; } isPromise("test"); // false isPromise($.Deferred()); // true isPromise($.Deferred().promise()); // true

Convertir una función en una cadena te da su código fuente, por lo que aquí comparo la fuente del método .then de un nuevo objeto Deferred con el del valor que me interesa. Tu valor no va a tener un .then Método con exactamente el mismo código fuente que un jQuery.Deferred o Promise 1 .

1. A menos que estés ejecutando en un entorno hostil, en cuyo caso probablemente deberías rendirte.

Si no está específicamente interesado en las promesas de jQuery, pero le gustaría detectar cualquier tipo de Promesa, incluidas las integradas de ECMAScript 6, puede probar si el valor es un objeto y tiene un método:

if (typeof value === ''object'' && typeof value.then === ''function'') { // handle a promise } else { // handle a concrete value }

Este es el enfoque de varias funciones de gestión de promesas definidas en ES6. Puede ver esto descrito en la especificación de las funciones de resolve(...) , citadas parcialmente a continuación:

Cuando se llama a una función de resolución de promesa F con resolución de argumento, se siguen los siguientes pasos:

[...]

  1. Si Tipo ( resolución ) no es Objeto, entonces
    1. Volver FulfillPromise ( promesa , resolución ).
  2. Deje entonces ser Get ( resolución , "then" ).
  3. Si entonces es una finalización abrupta, entonces
    1. Devolver RejectPromise ( promesa , luego . [[Valor]]).
  4. Deje que thenAction sea entonces . [[Valor]].
  5. Si IsCallable ( thenAction ) es falso , entonces
    1. Volver FulfillPromise ( promesa , resolución ).
  6. Ejecutar EnqueueJob ( "PromiseJobs" , PromiseResolveThenableJob, «Promesa, resolución, luego Acción» )

La solución rápida y sucia es probar si el objeto tiene una función then :

if (typeof message.then === ''function'') { //assume it''s a Deferred or fits the Deferred interface } else { //do other stuff }