example array jquery angularjs promise angular-promise

jquery - array - Obtener el estado de Angular diferido?



promise angular 6 example (4)

Actualizado:

Lamentablemente, esto no parece posible con $q . Tendrás que poner este código dentro de tu método.

myPromise() .then(function() { // everything in here resolved }, function() { // everything in here rejected }, function() { // everything in here pending (with progress back) });

Otro:

Esto es para la biblioteca Q no es angular $q pero similar.

Angular está inspirado en la biblioteca Q , revisa la fuente, en realidad no es tan aterrador. https://github.com/kriskowal/q/blob/v1/q.js

Puedes usar myPromise.inspect().state there are [''pending'', ''rejected'', ''fulfilled'']

Tu también tienes:

myPromise.isFulfilled(); myPromise.isPending(); myPromise.isRejected();

Consulte este JSfiddle y abra la consola para ver los resultados registrados. http://jsfiddle.net/S6LzP/

Más granular, Mirando la función de defer en la línea 488:

function defer() { // if "messages" is an "Array", that indicates that the promise has not yet // been resolved. If it is "undefined", it has been resolved. Each // element of the messages array is itself an array of complete arguments to // forward to the resolved promise. We coerce the resolution value to a // promise using the `resolve` function because it handles both fully // non-thenable values and other thenables gracefully. var messages = [], progressListeners = [], resolvedPromise; var deferred = object_create(defer.prototype); var promise = object_create(Promise.prototype); promise.promiseDispatch = function (resolve, op, operands) { var args = array_slice(arguments); if (messages) { messages.push(args); if (op === "when" && operands[1]) { // progress operand progressListeners.push(operands[1]); } } else { nextTick(function () { resolvedPromise.promiseDispatch.apply(resolvedPromise, args); }); } }; // XXX deprecated promise.valueOf = function () { if (messages) { return promise; } var nearerValue = nearer(resolvedPromise); if (isPromise(nearerValue)) { resolvedPromise = nearerValue; // shorten chain } return nearerValue; }; promise.inspect = function () { if (!resolvedPromise) { return { state: "pending" }; } return resolvedPromise.inspect(); }; if (Q.longStackSupport && hasStacks) { try { throw new Error(); } catch (e) { // NOTE: don''t try to use `Error.captureStackTrace` or transfer the // accessor around; that causes memory leaks as per GH-111. Just // reify the stack trace as a string ASAP. // // At the same time, cut off the first line; it''s always just // "[object Promise]/n", as per the `toString`. promise.stack = e.stack.substring(e.stack.indexOf("/n") + 1); } } // NOTE: we do the checks for `resolvedPromise` in each method, instead of // consolidating them into `become`, since otherwise we''d create new // promises with the lines `become(whatever(value))`. See e.g. GH-252. function become(newPromise) { resolvedPromise = newPromise; promise.source = newPromise; array_reduce(messages, function (undefined, message) { nextTick(function () { newPromise.promiseDispatch.apply(newPromise, message); }); }, void 0); messages = void 0; progressListeners = void 0; } deferred.promise = promise; deferred.resolve = function (value) { if (resolvedPromise) { return; } become(Q(value)); }; deferred.fulfill = function (value) { if (resolvedPromise) { return; } become(fulfill(value)); }; deferred.reject = function (reason) { if (resolvedPromise) { return; } become(reject(reason)); }; deferred.notify = function (progress) { if (resolvedPromise) { return; } array_reduce(progressListeners, function (undefined, progressListener) { nextTick(function () { progressListener(progress); }); }, void 0); }; return deferred; }

Sobre todo notablemente el método en la parte inferior deferred.notify .

Ejemplo de uso:

function requestOkText(url) { var request = new XMLHttpRequest(); var deferred = Q.defer(); request.open("GET", url, true); request.onload = onload; request.onerror = onerror; request.onprogress = onprogress; request.send(); function onload() { if (request.status === 200) { deferred.resolve(request.responseText); } else { deferred.reject(new Error("Status code was " + request.status)); } } function onerror() { deferred.reject(new Error("Can''t XHR " + JSON.stringify(url))); } function onprogress(event) { deferred.notify(event.loaded / event.total); } return deferred.promise; } requestOkText("http://localhost:3000") .then(function (responseText) { // If the HTTP response returns 200 OK, log the response text. console.log(responseText); }, function (error) { // If there''s an error or a non-200 status code, log the error. console.error(error); }, function (progress) { // Log the progress as it comes in. console.log("Request progress: " + Math.round(progress * 100) + "%"); });

Con deferreds jQuery estoy acostumbrado a poder verificar el estado actual de esta manera:

var defer = $.Deferred(); defer.state(); //Returns the state of the deferred, eg ''resolved''

¿Hay alguna manera de hacer lo mismo con los aplazamientos angulares? (o incluso mejores promesas)


La respuesta a su pregunta es: sí, hay una manera . Las otras respuestas cubren muy bien las limitaciones integradas de $q . Sin embargo, es fácil agregar una propiedad estatal a $q usando la función de decorador del servicio $provide .

$provide.decorator(''$q'', function ($delegate) { var defer = $delegate.defer; $delegate.defer = function() { var deferred = defer(); deferred.promise.state = deferred.state = ''pending''; deferred.promise.then(function() { deferred.promise.state = deferred.state = ''fulfilled''; }, function () { deferred.promise.state = deferred.state = ''rejected''; }); return deferred; }; return $delegate; });

Coloque este decorador dentro de un bloque de config y todos los objetos diferidos y promediados de $q tendrán una propiedad de state con el valor pendiente , cumplido o rechazado .

Mira esto

¿Escéptico?

está efectivamente modificando $ q en sí, envolviendo cada aplazado con otro diferido

Actualmente, este no es el caso. $q constructor original defer() $q se llama exactamente una vez. Simplemente está decorado con funcionalidad adicional mediante la conexión interna de un controlador de eventos a través de then . [Tenga en cuenta que se crea una instancia de un objeto defer adicional como resultado de la devolución de llamada adicional que se crea automáticamente con cada objeto diferido ... lo cual es de esperar porque así es como funciona angular internamente.

esto no funcionaría porque las promesas no deberían crearse con diferido sino encadenadas de promesas que se devuelven desde apis

Tenga en cuenta que este código decorará cada objeto diferido (y por lo tanto, promise ) creado por el servicio $q . Esto significa que cualquier API que utilice $ q se decorará automáticamente con la propiedad del state . Por lo tanto, independientemente de cómo use $q , ya sea con alguna API o por sí mismo, esta solución decora tanto el objeto deferred como la promise , y yo he proporcionado el plunk para probarlo.

Digno de producción?

Este enfoque es comprobable por unidad , se garantiza que no se romperá ninguna aplicación que ya esté usando $q , y es flexible en el sentido de que luego podría agregar decoradores adicionales a $q sin modificar los anteriores.


Actualización :

Debido a la refacturación de $ q esto ahora es posible aunque no documentado:

promise.$$state.status === 0 // pending promise.$$state.status === 1 // resolved promise.$$state.status === 2 // rejected

Original :

A diferencia de la mayoría de las bibliotecas de promesas (Bluebird, Q, cuando, RSVP, etc.), $ q no expone una API de inspección síncrona.

No hay forma de lograr esto desde el exterior.

Tienes que llamar. .then la promesa y el código en ese controlador se ejecutarán cuando la promesa cumpla.


Organicé una solución inspirada en las respuestas de Gil y Travis, que decora el constructor Promise con métodos más cercanos a la implementación de Q.

Tenga en cuenta que esta decoración se basa en Promise.$$state . Esto fue construido para Angular 1.6.4, y teóricamente debería funcionar hasta 1.3.x, pero no hay garantías en eso o lanzamientos futuros:

(function() { ''use strict''; angular .module(''your.module.name.goes.here'') .config(configBlock); /** @ngInject */ configBlock.$inject = [''$provide'']; function configBlock($provide) { $provide.decorator(''$q'', [''$delegate'', function ($delegate) { console.log($delegate); var Promise = $delegate.prototype.constructor; Promise.prototype.inspect = function () { var inspect = {}; switch (this.$$state.status) { case -1: case 0: inspect.state = ''pending''; break; case 1: inspect.state = ''fulfilled''; break; case 2: inspect.state = ''rejected''; break; default: inpsect.state = ''unknown''; } return inspect; }; Promise.prototype.isFulfilled = function () { return this.inspect().state === ''fulfilled''; } Promise.isFulfilled = function (obj) { if (obj.constructor !== Promise) { return true; } return obj.isFulfilled(); } Promise.prototype.isRejected = function () { return this.inspect().state === ''rejected''; } Promise.isRejected = function (obj) { if (obj.constructor !== Promise) { return false; } return obj.isRejected(); } Promise.prototype.isPending = function () { return this.inspect().state === ''pending''; } Promise.isPending = function (obj) { if (obj.constructor !== Promise) { return false; } return obj.isPending(); } return $delegate; }]); } })();