when then method example done await async jquery jquery-deferred

jquery - then - ¿Qué son objetos diferidos?



jquery when function done (4)

jQuery 1.5 agrega "objetos diferidos". ¿Qué son y qué hacen exactamente?


Corrígeme si estoy equivocado, pero recientemente me hizo clic en que es esencialmente un Runner de tareas asíncronas. La promesa es un contrato resultante, que garantiza que recibirá ... algo, pero sin garantía de cuándo lo obtendrá.


En lugar de decirte lo que hace, te mostraré lo que hace y lo explicaré.

Una copia de la fuente relacionada de jQuery 1.5 con anotaciones explicando lo que está haciendo. Creo que los comentarios son en su mayoría correctos.

Esto puede ser beneficioso

// promiseMethods. These are the methods you get when you ask for a promise. // A promise is a "read-only" version // fullMethods = "then done fail resolve resolveWith reject rejectWith isResolve isRejected promise cancel".split(" ") // As you can see it removes resolve/reject so you can''t actaully trigger a // anything on the deferred object, only process callbacks when it "finishes". promiseMethods = "then done fail isResolved isRejected promise".split(" "), // Create a simple deferred (one callbacks list) /* Class: _Deferred. * methods: done, resolve, resolveWith, isResolved * internal method: cancel * * Basically allows you to attach callbacks with the done method. * Then resolve the deferred action whenever you want with an argument. * All the callbacks added with done will be called with the resolved argument * Any callbacks attached after resolvement will fire immediatly. * * resolveWith allows you to set the this scope in the callbacks fired. * * isResolved just checks whether it''s resolved yet. * * cancel blocks resolve/resolveWith from firing. the methods added throug * done will never be called */ _Deferred: function () { var // callbacks list callbacks = [], // stored [ context , args ] // stores the context & args that .resolve was called with fired, // to avoid firing when already doing so firing, // flag to know if the deferred has been cancelled // in Deferred cancel gets called after the first resolve call cancelled, // the deferred itself deferred = { // done( f1, f2, ...) done: function () { if (!cancelled) { var args = arguments, i, length, // elem in callback list elem, // type of elem in callback list type, // cached context & args for when done is called // after resolve has been _fired; // If resolve has been called already if (fired) { // mark it locally _fired = fired; // set fired to 0. This is neccesary to handle // how done deals with arrays recursively // only the original .done call handles fired // any that unwrap arrays and call recursively // dont handle the fired. fired = 0; } // for each function append it to the callback list for (i = 0, length = args.length; i < length; i++) { elem = args[i]; type = jQuery.type(elem); // if argument is an array then call done recursively // effectively unwraps the array if (type === "array") { // def.done([f1, f2, f3]) goes to // def.done(f1, f2, f3) through the apply deferred.done.apply(deferred, elem); } else if (type === "function") { // if its a function add it to the callbacks callbacks.push(elem); } } // if it''s already been resolved then call resolveWith using // the cahced context and arguments to call the callbacks // immediatly if (_fired) { deferred.resolveWith(_fired[0], _fired[1]); } } return this; }, // resolve with given context and args resolveWith: function (context, args) { // if its been cancelled then we can''t resolve // if it has fired then we can''t fire again // if it''s currently firing then we can''t fire. This check is // there because of the try finally block. It ensures we // cant call resolve between the try & finally in the catch phase. if (!cancelled && !fired && !firing) { firing = 1; // try block because your calling external callbacks // made by the user which are not bugfree. // the finally block will always run no matter how bad // the internal code is. try { while (callbacks[0]) { callbacks.shift().apply(context, args); } // cache the content and arguments taht have been called // and set firing to false. } finally { fired = [context, args]; firing = 0; } } return this; }, // resolve with this as context and given arguments // just maps to resolveWith, this sets the this scope as normal // maps to this.promise which is the read only version of Deferred. resolve: function () { deferred.resolveWith(jQuery.isFunction(this.promise) ? this.promise() : this, arguments); return this; }, // Has this deferred been resolved? // checks whether it''s firing or if it has fired. isResolved: function () { return !!(firing || fired); }, // Cancels the action. To be used internally cancel: function () { cancelled = 1; callbacks = []; return this; } }; return deferred; }, /* Class: Deferred. * methods: then, done, fail, resolve, reject, resolveWith, rejectWith, isResolved, isRejected, promise * * then is a shortcut for both assigning done & fail in one function. * * This one has two underlying lists with different semantic meanings. You * can bind to both the done callbacks and the fail callbacks then either * resolve or reject your Deferred object. * * You can check whether it has been resolved or rejected. useful to see * Afterwards which one has happened. * * Call .promise to return a new object which doesn''t have the resolve/reject * methods on it. This means you can only bind to it and not resolve/reject it. * This is effectively read-only. * */ // Full fledged deferred (two callbacks list) Deferred: function (func) { // the main deferred which deals with the success callbacks var deferred = jQuery._Deferred(), // the failure deferred which deals with the rejected callbacks failDeferred = jQuery._Deferred(), // the read only promise is cached. promise; // Add errorDeferred methods, then and promise jQuery.extend(deferred, { // def.then([f1, f2, ...], [g1, g2, ...] is a short hand for // def.done([f1, f2, ...]) // def.fail([g1, g2, ...]) then: function (doneCallbacks, failCallbacks) { // fail exists here because this code will only run after // deferred has been extended. deferred.done(doneCallbacks).fail(failCallbacks); return this; }, // map def.fail to the second underlying deferred callback list // map all the other methods for rejection/failure to the underlying // failDeffered object so that Deferred has two callback lists stored // internally. fail: failDeferred.done, rejectWith: failDeferred.resolveWith, reject: failDeferred.resolve, isRejected: failDeferred.isResolved, // Get a promise for this deferred // If obj is provided, the promise aspect is added to the object // no clue what to do with "i" promise: function (obj, i /* internal */ ) { // if no argument is passed then just extend promise if (obj == null) { // if cached return the cache. if (promise) { return promise; } // set promise & arg to be {} promise = obj = {}; } // for each promiseMethods in the read only promise list i = promiseMethods.length; while (i--) { // set the deferred method on the object obj[promiseMethods[i]] = deferred[promiseMethods[i]]; } // returns the "read-only" deferred without // resolve, resolveWith, reject & rejectWith. // So you cant "resolve" it but only add "done" functions return obj; } }); // Make sure only one callback list will be used // if either resolve or reject is called cancel both. // this means that the one that has been called cant be called again // and the other one will never be called. So only the done or the fail // methods will ever be called deferred.then(failDeferred.cancel, deferred.cancel); // Don''t mess with cancel! // Unexpose cancel delete deferred.cancel; // Call given func if any // function argument to be called. This was passed in. Allows you to // handle the deferred object after creating a new one, both as this scope // and as a new argument. if (func) { func.call(deferred, deferred); } return deferred; }, /* Method: when * Arguments: none OR 1 of type(any & !deferred) OR n of type(deferred). * * If no arguments are passed then it gets resolved immediatly. A good way to * call multiple callback functions? Don''t really know a good use of $.when() * * If one argument is passed and its not a deferred object then it resolves * immediatly and passes that argument to all the done callbacks attached. * * if n arguments are passed of type deferred object then the the done callbacks * will only fire if all of them succeed. If a single one fails then the * fail callbacks fire. * * Returns a promise read-only deferred object */ // Deferred helper when: function (object) { var args = arguments, length = args.length, // If you pass in a deferred object then set deferred to be the promise // if you pass in anything else then set deferred to be a new deferred deferred = length <= 1 && object && jQuery.isFunction(object.promise) ? object : jQuery.Deferred(), // cache the promise promise = deferred.promise(), // store an array resolveArray; // if multiple objects are passed in if (length > 1) { // create an arrey to store of values. resolveArray = new Array(length); // for each object that we wait on jQuery.each(args, function (index, element) { // when that object resolves then jQuery.when(element).then(function (value) { // store value in the array or store an array of values in it resolveArray[index] = arguments.length > 1 ? slice.call(arguments, 0) : value; // if length === 1 then we finished calling them all if (!--length) { // resolve the deferred object with the read only promise // as context and the resolved values array as the argument deferred.resolveWith(promise, resolveArray); } // if any fail then we reject or deferred }, deferred.reject); }); // if deferred was newly created but there was only one argument then // resolve it immediatly with the argument. } else if (deferred !== object) { deferred.resolve(object); } // return the read-only deferred. return promise; },


Mientras trabajamos en Javascript, encontramos situaciones donde las llamadas a funciones son asincrónicas. Ese es el flujo de la función Calee (digamos X) no espera la función asíncrona llamada (Let say Y). Un ejemplo típico es cuando hacemos llamadas a un servidor para obtener algunos datos de una base de datos o una página HTML. Si esas llamadas no fueron asincrónicas, la interfaz de usuario estará bloqueada esperando que el servidor responda. Esta naturaleza asíncrona conduce a un problema cuando desea ejecutar cosas en un orden, por ejemplo, desea imprimir algo después de que Y (asynch) finaliza la ejecución o la obtención de datos. Aquí jQuery nos proporciona un objeto deffered. Básicamente, jQuery se ha ocupado de todos los códigos repetitivos que generalmente escribimos para resolver esta situación. Aquí hay un ejemplo simple:

$.ajax({ ... }).done(function(){ //write here what you wish to do when this ajax call is success }).fail(function(){ //write here what you wish to do on failure of this ajax call }); //see more on jQuery Deferred page

Puede escribir su propia función diferida (asynch)

function DoSomethingTimeConsumingAsynch(){ var deferred = $.Deferred(); _.defer(function(){ //I am using underscore, you can also use setTimeout ... deferred.resolve();//When the process is done successfully ... deferred.reject(); //When the process has failed }); return deferred; } //HEre how to use your own asynch function DoSomethingTimeConsumingAsynch() .done(function(){ //this will be invoked on success }) .fail(function(){ //this will be invoked on failure })

Espero que esto haya ayudado.


Objeto diferido

A partir de jQuery 1.5, el objeto aplazado proporciona una forma de registrar múltiples devoluciones de llamadas en colas de devolución de llamada autogestionadas, invocar colas de devolución de llamada según corresponda y retransmitir el estado de éxito o falla de cualquier función síncrona o asíncrona.

Métodos diferidos:

  • deferred.done()
    • Agregue controladores para llamar cuando se resuelva el objeto aplazado.
  • deferred.fail()
    • Agregue controladores para llamar cuando se rechaza el objeto aplazado.
  • deferred.isRejected()
    • Determine si un objeto diferido ha sido rechazado.
  • deferred.isResolved()
    • Determine si se ha resuelto un objeto diferido.
  • deferred.reject()
    • Rechaza un objeto diferido y llama a cualquier failCallbacks con las args dadas.
  • deferred.rejectWith()
    • Rechazar un objeto diferido y llamar a cualquier FallCallbacks con el contexto y args dados.
  • deferred.resolve()
    • Resuelva un objeto diferido y llame a cualquier doneCallbacks con los args dados.
  • deferred.resolveWith()
    • Resuelva un objeto diferido y llame a cualquier DoneCallbacks con el contexto y args dados.
  • deferred.then()
    • Agregue controladores para llamar cuando el objeto diferido se resuelve o rechaza.

Diferido en acción:

$.get("test.php").done( function(){ alert("$.get succeeded"); } ); $.get("test.php") .done(function(){ alert("$.get succeeded"); }) .fail(function(){ alert("$.get failed!"); });

Y parece que las devoluciones de llamada del método ajax () existentes se pueden encadenar en lugar de declarar en la configuración:

var jqxhr = $.ajax({ url: "example.php" }) .success(function() { alert("success"); }) .error(function() { alert("error"); }) .complete(function() { alert("complete"); });

Ejemplo de trabajo de la publicación del blog Eric Hynds : http://jsfiddle.net/ehynds/Mrqf8/

jqXHR

A partir de jQuery 1.5, el método $ .ajax () devuelve el objeto jXHR, que es un superconjunto del objeto XMLHTTPRequest. Para obtener más información, consulte la sección JXHR de la entrada $ .ajax

De JQUERY 1.5 LIBERADO :

OBJETOS DIFERIDOS

Junto con la reescritura del módulo Ajax, se introdujo una nueva característica que también se puso a disposición del público: Objetos diferidos . Esta API le permite trabajar con valores de retorno que pueden no estar presentes de inmediato (como el resultado de retorno de una solicitud Ajax asincrónica). Además, te da la posibilidad de adjuntar múltiples controladores de eventos (algo que antes no era posible en la API de Ajax).

Además, puede crear sus propios objetos diferidos utilizando jQuery.Deferred expuesto. Se puede encontrar más información sobre esta API en la documentación del Objeto Diferido .

Eric Hynds ha escrito un buen tutorial sobre el uso de diferidos en jQuery 1.5 .