Bonjour,

Je d�veloppe actuellement une application e-commerce dont le front est fait en TypeScript / Angular, mais je suppose que la question s'applique aussi g�n�ralement au JavaScript.

La recherche de produits est bas�e sur un moteur de recherche externe au backend auquel j'envoie les mots-cl�s et me retourne la liste des produits correspondants avec leur id. Ensuite, je fais un appel AJAX vers le backend avec les ids de ces produits et qui me retourne diff�rentes informations sur ceux-ci, notamment le prix, le plus important.

Je ne veux pas surcharger le serveur avec un trop grand nombre de requ�tes, j'envoie donc une liste d'ids en une seule fois. J'utilise une classe service qui se charge de retourner � un composant produit son prix une fois qu'il a �t� r�cup�r�, � l'aide d'un observable, fonctionnement classique. Sauf que le service, quand on lui demande un prix, ne va pas chercher un seul prix mais celui de l'ensemble des produits qui lui ont �t� demand�s � un certain moment, donc je ne peux pas utiliser un syst�me classique de demande de prix qui retourne un observable avec uniquement le prix du produit en question.

Donc voil� comment je proc�de actuellement : le produit demande son prix au service en lui envoyant son id. Le service accumule la liste des ids des demandes au m�me moment, puis envoie la requ�te AJAX et stocke le les r�sultats dans un objet (tableau avec liste d'objets produit produits et leurs propri�t�s). Chaque composant produit s'abonne au service. Une fois que le service a r�cup�r� la liste des produits demand�s, il envoie un par un les ids de ces produits � tous les composants produits abonn�s. Le produit, lorsqu'il a re�u cet id, v�rifie si l'id correspond au sien, et si c'est le cas, demande le prix au service qui est alors capable de le lui renvoyer directement en allant le chercher dans ses donn�es stock�es.

Pour �tre plus claire, le produit qui demande son prix n'attend pas une r�ponse lors de cet appel, il informe seulement le service qu'il doit r�cup�rer le prix, ensuite il re�oit un push lorsque le prix est disponible (ce qui peut �tre le cas imm�diatement lorsqu'il a �t� stock�).

Ca fonctionne tr�s bien mais je ne suis pas satisfaite du fonctionnement car cela d�clenche beaucoup d'�v�nements inutiles et j'ai peur que sur un navigateur aux ressources limit�es cela ne cr�e des ralentissements. Si j'ai 50 produits � afficher au m�me moment, chaque composant produit abonn� va recevoir 50 retours du service dont 49 contiennent donc une information inutile et je me demandais s'il y aurait une meilleure fa�on de faire.

En gros, je voudrais que les produits demandent chacun leur prix au service, que celui-ci r�cup�re par une requ�te tous les prix demand�s au m�me moment puis n'envoie l'information qu'au produit concern�. Le fonctionnement serait donc le suivant :

- L'utilisateur tappe ses mots cl�s et la requ�te est envoy�e au moteur de recherche
- L'application re�oit la liste des produits correspondant et les affiche dans le template sous forme de composants
- Lorsque le composant est cr��, il s'abonne au service pour pouvoir recevoir des push
- Le produit demande son prix au service
- Le service attend d'avoir la liste des produits ayant besoin d'un prix et d�clenche la requ�te
- Une fois la r�ponse re�ue, le service envoie � chacun des produits abonn�es les donn�es le concernant et uniquement celles-ci
- Lorsque le composant est d�truit, il se d�sabonne �videmment du service afin de ne pas accumuler les demandes et r�ponses

Est-il possible de faire cela ? Je dois bien avouer que ma compr�hension de la librairie rxjs est assez limit�e donc je ne connais pas toutes les possibilit�s offertes.

Voil� un r�sum� de mon code actuel :

Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
class ProductComponent()
{
	public product: Product; // données passée par le template
	private productServiceSubscription; // abonnement aux push du service
 
	constructor(public productsService: ProductService) { } // service passé par injection de dépendance, instancié une seule fois
 
	public componentInit() // appelé lorsque le composant est affiché dans le template
	{
		this.productService.askForPrice(this.product.id);
 
		this.productServiceSubscription.getSubscription().subscribe((productId: number) => {
			if (productId === this.product.id) {
				this.product.price = this.productService.getPriceById(this.product.id);
			}
		});
	} 
 
	public componentDestroy()
	{
		this.productServiceSubscription.unsubscribe();
	}
}
 
class ProductsService()
{
	private products: Product[] = [];
 
	private requestTimeout;
	private subscription: Subject<productId: number> = new Subject();
	private productsQueue: number[] = []; // liste des produits en attente d'un prix
 
	public getSubscription(): Subject<productId>
	{
		return this.subscription;
	}
 
	public askForPrice(productId: number): void
	{
		// Le produt a déjà été stocké, on le retourne immédiatement
		if (this.getProductById(productId)) {
			this.subscription.next(productId);
			return;
		}
 
		// Le produt n'est pas stocké, on se prépare à le demander à l'api
 
		clearTimeout(this.requestTimeout); // système de timeout permettant d'attendre d'avoir reçu une liste de produits avant de déclencher la requête
 
		this.productsQueue.push(producId);
 
		this.requestTimeout = setTimeout(() => {
			this.getPricesFromApi();
		}, 200);
	}
 
	private getPricesFromApi(): void
	{
		const client = new HttpClient();
 
		client.get('url-de-l\'api', this.productsQueue).subscribe(products: Product[] => {
			for (const product in products) {
				if (!this.getProductById(product.id)) { // on évite de stocker un même produit plusieurs fois
					this.products.push(product);
				}
 
				this.subscription.next(product.id);
			}
		});
 
		this.productsQueue = [];
	}
 
	public getPriceById(productId: number): number
	{
		return this.getProductById().price;
	}
 
	// Retourne un produit s'il est stocké dans la variable products locale
	private getProductById(productId: number): Product|null
	{
		// ....
	}
}