Comment puis-je utiliser l'objet jQuery.Deferred ?

Index

Les objets différés (Deferred object) sont un moyen utile pour structurer votre code.

Un objet différé est un objet :

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

Tests unitaires avec QUnit.