2011-02-01 15 views

risposta

96

passivi oggetto

Al jQuery 1.5, l'oggetto differito fornisce un modo per registrare più callback in code callback autogestito, richiamare code callback come appropriato, e trasmettere il successo o stato di avaria di qualsiasi sincrono o funzione asincrona.

Metodi anticipate:

  • deferred.done()
    • aggiungere i gestori per essere chiamato quando l'oggetto differite è stato risolto.
  • deferred.fail()
    • Aggiungere i gestori di essere chiamato quando l'oggetto differita viene respinta.
  • deferred.isRejected()
    • determinare se un oggetto differita è stata respinta.
  • deferred.isResolved()
    • determinare se un oggetto differite è stato risolto.
  • deferred.reject()
    • Reject un oggetto differiti e chiamare qualsiasi failCallbacks con args indicate.
  • deferred.rejectWith()
    • Reject un oggetto differiti e chiamare qualsiasi failCallbacks con il contesto dato e args.
  • deferred.resolve()
    • risolvere un oggetto differiti e chiamare qualsiasi doneCallbacks con args indicate.
  • deferred.resolveWith()
    • risolvere un oggetto differiti e chiamare qualsiasi doneCallbacks con il contesto dato e args.
  • deferred.then()
    • Aggiungere i gestori di essere chiamato quando l'oggetto differite è stato risolto o rifiutato.

differita In Azione:

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

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

e sembra che l'Ajax esistente() metodo callback può essere incatenato piuttosto che dichiarò nelle impostazioni:

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

Esempio di lavoro From Eric Hynds blog post: http://jsfiddle.net/ehynds/Mrqf8/


jqXHR

Come di jQuery 1.5, il metodo $ .ajax() restituisce l'oggetto jXHR, che è un superset del l'oggetto XMLHttpRequest. Per ulteriori informazioni, vedere thejXHR sezione del $ .ajax ingresso


Da JQUERY 1.5 RELEASED:

OGGETTI ANTICIPATE

Insieme con la riscrittura del modulo di Ajax una nuova funzionalità era introdotto che è stato anche reso pubblico disponibile: Deferred Objects. Questa API consente di lavorare con i valori restituiti che potrebbero non essere immediatamente (come il risultato di ritorno da una richiesta Ajax asincrona). Inoltre ti dà l'abilità di collegare più gestori di eventi (qualcosa che non era precedentemente possibile nell'API Ajax).

Inoltre, è possibile creare il proprio oggetti differite utilizzando l'esposto jQuery.Deferred. Maggiori informazioni su su questa API sono disponibili nella documentazione Deferred Object.

Eric Hynds ha scritto un buon tutorial su Using Deferreds in jQuery 1.5.

+17

Spiegare di più. Come posso creare i miei oggetti differiti personalizzati. Come funzionano? – user113716

+3

In realtà sono serio. Questa è una buona domanda su una nuova funzionalità. Non ho idea di come funzionano, e penso che sarebbe bello se StackOverflow avesse questa domanda ben spiegata per coloro che ne faranno domanda in futuro. Aggiornamenti – user113716

+1

: Penso che la definizione di "Differita" sopra quella che ho aggiunto in alto fornisca una visione più chiara di ciò che sta effettivamente facendo. Sembra essere più di essere in grado di concatenare i callback piuttosto che doverli dichiarare nelle impostazioni passate in una funzione. – hunter

12

Piuttosto che dirti cosa fa, ti mostrerò cosa fa e come spiegarlo.

Una copia della sorgente correlata di jQuery 1.5 con annotazioni che spiegano cosa sta facendo. Penso che i commenti siano per lo più corretti.

Questo può essere di beneficio

// 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; 
}, 
+6

Questo leggerà molto meglio se non si dispone di una barra di scorrimento orizzontale:/ – gnarf

+0

@gnarf ['Problema risolto]] (http://jsbin.com/ivate4/edit). Btw questa è la fonte 1.5beta Penso che ci siano alcuni cambiamenti in 1.6 – Raynos

9

mi corregga se sbaglio, ma di recente cliccato per me che è essenzialmente un Asynchronous Task Runner. La promessa è un contratto di risultato, che garantisce di ricevere ... qualcosa, ma senza la garanzia di quando lo capirai.

+0

Quindi, solo vino vecchio in una nuova bottiglia! – dotslash

3

Mentre si lavora in Javascript, incontriamo situazioni in cui le chiamate di funzione sono asincrone.Quello è il flusso della funzione calee (diciamo X) che non aspetta la funzione asincrona chiamata (diciamo Y). Un tipico esempio è quando effettuiamo chiamate a un server per recuperare alcuni dati da un database o da una pagina HTML. Se tali chiamate non erano asincrone, l'interfaccia utente resterà bloccata in attesa che il server risponda. Questa natura asincrona porta a un problema quando si desidera eseguire le cose in un ordine, ad esempio, si desidera stampare qualcosa dopo che Y (asynch) ha terminato l'esecuzione o il recupero dei dati. Qui jQuery ci fornisce Oggetto Deffered. Fondamentalmente, jQuery si è preso cura di tutto il codice standard che di solito scriviamo per risolvere questa situazione. Ecco un semplice esempio:

$.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 

È possibile scrivere il proprio differita (asincrono) Funzione

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 
}) 

Spero che questo ha aiutato.

Problemi correlati