Les objets différés (Deferred object) sont un moyen utile pour structurer votre code.
Un objet différé est un objet :
-
qui permet de chaîner les instructions ;
-
qui peut prendre deux états (succès (done) ou échec (fail)) ;
-
qui gère une file d'attente de fonctions de rappel (callback) pour chacun de ses états ;
-
qui peut enregistrer plusieurs fonctions de rappel dans une file d'attente ;
-
qui, lorsque son état est déterminé (succès ou échec), exécute dans l'ordre d'insertion, chacune des
fonctions de rappel contenues dans la file d'attente correspondant à son état.
var jObjDif = $.Deferred();
crée un objet différé.
jObjDif.done()
,pour ajouter une fonction de rappel à la file d'attente qui
sera appelée en cas de succès.
jObjDif.fail()
, pour ajouter une fonction de rappel à la file d'attente qui
sera appelée en cas d'échec.
jObjDif.always()
, pour ajouter une fonction de rappel à la file d'attente qui
sera toujours exécutée lorsque la promesse se réalisera par un succès ou par un échec.
jObjDif.then( doneCallback, failCallback )
, pour ajouter une fonction ou un tableau (array)
de fonctions aux files d'attente.
jObjDif.pipe( [ doneFilterFunction ], [ failFilterFunction ] )
, retourne une nouvelle
promesse (un objet différé) qui filtre le statut et les valeurs de l'objet différé original au
travers d'une fonction.
jObjDif.resolve( arguments )
, passe l'objet différé dans l'état "succès" ce qui déclenche
l'activation de la file d'attende correspondante.
jObjDif.reject( arguments )
, passe l'objet différé dans l'état "échec" ce qui déclenche
l'activation de la file d'attende correspondante.
$.when( jObjDif1, jObjDif2 )
, génère un objet différé pour gérer le résultat final d'un
ensemble d'objets différés, voir l'exemple.
Exemple 1 : avec des objets différés globaux.
/*
* Cette fonction sera utilisée comme une fonction
* de rappel qui sera appelée en cas de succès.
*/
var funcDone = function(){
console.log( "C'est un succès !", arguments );
};
/*
* Cette fonction sera utilisée comme une fonction
* de rappel qui sera appelée en cas d'échec.
*/
var funcFail = function(){
console.log( "C'est un échec !", arguments );
};
/*
* Création des objets différés.
*/
var jObjDif1 = $.Deferred(),
jObjDif2 = $.Deferred();
/*
* Après la création de l'objet, on lui ajoute par
* la méthode then une ou plusieurs fonctions de
* rappel qui seront activées en cas de succès et
* une ou plusieurs fonctions de rappel qui seront
* activées en cas d'échec.
*
* La méthode then accepte, comme ici, une seule fonction
* ou un tableau (array) de fonctions.
*
* Les fonctions de rappel seront activées dans l'ordre
* de leur ajout à la file d'attente.
*/
jObjDif1.then( funcDone, funcFail );
jObjDif2.then( funcDone, funcFail );
/*
* On termine le premier test par un succès en
* appelant la méthode resolve avec ou sans
* arguments.
*/
var funcTest1 = function(){
console.log( "La fonction funcTest1 a été appelée" );
jObjDif1.resolve( "funcTest1", arguments );
};
/*
* On termine le second test par un échec en
* appelant la méthode reject avec ou sans
* arguments.
*/
var funcTest2 = function(){
console.log( "La fonction funcTest2 a été appelée" );
jObjDif2.reject( "funcTest2", arguments );
};
/*
* $.when() est utile pour gérer le résultat final d'un
* ensemble d'objets différés.
*
* $.when() génère un objet différé, ce qui permet
* d'enchainer les instructions ici then().
*/
$.when( jObjDif1, jObjDif2 ).then(
function(){
console.log( "Le résultat final est un succès !", arguments );
},
function(){
console.log( "Le résultat final est un échec !", arguments );
}
);
funcTest1( "hello" );
funcTest2( "Oops" );
/*
* La fonction funcTest1 a été appelée
* C'est un succès ! ["funcTest1", ["hello"]]
*
* La fonction funcTest2 a été appelée
* C'est un échec ! ["funcTest2", ["Oops"]]
*
* Le résultat final est un échec ! ["funcTest2", ["Oops"]]
*/
Exemple 2 : avec des fonctions qui retournent un objet différé.
/*
* Cette fonction sera utilisée comme une fonction
* de rappel qui sera appelée en cas de succès.
*/
var funcDone = function(){
console.log( "Le résultat final est un succès !", arguments );
};
/*
* Cette fonction sera utilisée comme une fonction
* de rappel qui sera appelée en cas d'échec.
*/
var funcFail = function(){
console.log( "Le résultat final est un échec !", arguments );
};
/*
* Cette fonction sera utilisée comme une fonction
* de rappel qui sera appelée en cas de succès et
* en cas d'échec.
*/
var funcAlways = function(){
console.log( "L'objet différé final a été créé !", arguments );
};
/*
* Premier test, inférieur à 6 charactères.
*/
function test1(){
var jObjDif = $.Deferred();
if ( String( arguments[ 0 ] ).length < 6 ){
jObjDif.resolve( "test1", arguments );
} else {
jObjDif.reject( "test1", arguments );
}
// Retourne l'objet différé dans l'état "succès" ou "échec".
return jObjDif.promise();
}
/*
* Second test, supérieur à 6 charactères.
*/
function test2(){
var jObjDif = $.Deferred();
if ( String( arguments[ 0 ] ).length > 6 ){
jObjDif.resolve( "test2", arguments );
} else {
jObjDif.reject( "test2", arguments );
}
// Retourne l'objet différé dans l'état "succès" ou "échec".
return jObjDif.promise();
}
// Objet différé final n° 1
var jObjDifFinal1 = $.when( test1( "Hello" ), test2( "Bonjour" ) );
jObjDifFinal1
.done( funcDone )
.fail( funcFail )
.always( funcAlways() );
/*
* Le résultat final est un succès ! [Array[2], Array[2]]
* L'objet différé jObjDifFinal a été créé ! [Array[2], Array[2]]
*/
// Objet différé final n° 2
var jObjDifFinal2 = $.when( test1( "Bonjour" ), test2( "Bonjour" ) );
jObjDifFinal2
.done( funcDone )
.fail( funcFail )
.always( funcAlways );
/*
* Le résultat final est un échec ! ["test1", Arguments[1]]
* L'objet différé final a été créé ! ["test1", Arguments[1]]
*/
Attention
/*
* Si on oublie de fixer l'état de l'objet différé,
* la promesse n'est jamais tenue et l'objet final
* n'est jamais créé.
*/
function test3(){
var jObjDif = $.Deferred();
// On oublie de fixer l'état de l'objet différé
return jObjDif.promise();
}
var jObjDifFinal3 = $.when( test1( "Hello" ), test2( "Bonjour" ), test3( "Oops" ) );
jObjDifFinal3
.done( funcDone )
.fail( funcFail )
.always( funcAlways );