J'ai une zone de texte qui pour chaque fois qu'un utilisateur entrait une lettre, je effectue une recherche avec une demande AJAX et montrez le résultat "Live" pour l'utilisateur. Souvent, lorsqu'un utilisateur représente les lettres qu'il prend plus de temps pour que la demande soit faite que pour l'utilisateur de saisir une nouvelle lettre, une nouvelle demande est donc effectuée avant la fin du premier. Ce serait bien mieux si le premier pourrait se terminer avant de faire la demande suivante. Existe-t-il un bon moyen de faire une nouvelle demande si la dernière demande est terminée?
Ceci est mon code JQuery: P>
$("#MyTextBox").change(function() { if (this.value.length > 2) { $.ajax({ type: "GET", url: "http://www.domain.com/Service.svc/Search?keyword=" + this.value, dataType: "json", success: function(data) { //here I have some code that shows the result for the user } }); } });
5 Réponses :
Vous pouvez utiliser ajaxcomplete afin que vous sachiez quand une demande a terminé avant de faire une nouvelle demande. P>
Vous pouvez le combiner avec BIND / DÉLIND afin que l'événement de changement soit ajouté manuellement, puis non lié lorsqu'une demande AJAX commence et rebondit lorsque la demande AJAX se termine. P>
Vous pouvez créer un booléen qui sera vrai ou faux selon le cas s'il y a une demande déjà. Configurez-le sur TRUE lorsque vous démarrez une demande et le remettez-le sur False dans votre fonction de rappel.
var request_in_process = false; $("#MyTextBox").change(function() { if (this.value.length > 2 && !request_in_process) { request_in_process = true; $.ajax({ type: "GET", url: "http://www.domain.com/Service.svc/Search?keyword=" + this.value, dataType: "json", success: function(data) { request_in_process = false; //here I have some code that shows the result for the user } }); } });
Merci! C'était exactement ce que je cherchais. Mais pour une raison quelconque lors de la frappe dans mon texte, on dirait que chaque fois que je saisis une lettre, c'est un peu de buggy et chaque lettre apparaît avec une sorte de retard. La demande AJAX devrait être envoyée ASYNC afin que cela ne puisse pas affecter la zone de texte le devrait?
Il serait préférable d'attribuer une fonction avec un code de nettoyage comme requier_in_progress code> dans le paramètre
complet code> plutôt que
succès code> au cas où la requête échoue.
Vous pouvez abandonner une demande AJAX. Gardez une trace de la demande comme une variable et abandonnez-le avant de relancer la demande.
var request = $.ajax({ ... }); request.abort();
Comme Ceejayoz déjà mentionné, vous devez abandonner la demande précédente. (En attente de la demande rendra les utilisateurs en colère si elles ne peuvent pas taper comme elles le souhaitent. Et préférez que les demandes plus anciennes sur les plus récentes rendent les résultats obsolètes.) Alors, qu'en est-il:
var request = null; //... $("#MyTextBox").change(function() { if (this.value.length > 2) { if (request && request.abort) request.abort(); request = $.ajax({ type: "GET", url: "http://www.domain.com/Service.svc/Search?keyword=" + this.value, dataType: "json", success: function(data) { //here I have some code that shows the result for the user request = null; }); } });
Voici une implémentation légèrement plus robuste. Fondamentalement, nous enregistrons l'objet Ajax (c'est-à-dire l'objet Promise) de la fermeture afin que les appels ultérieurs puissent le regarder. Si les appels suivants constatent que l'état de la demande est en attente, il ajoutera des rappels à cette demande en attente au lieu de générer une nouvelle demande. JQuery déclenchera tous les rappels dans la même séquence qu'ils ont été ajoutés. Cependant, il est possible que le même appelant essaie de créer de nouveau la demande et de nouveau. Pour protéger contre cela, j'ai ajouté le paramètre CallerID. Si même appelant a de nouveau apporté la demande alors que la demande précédente était toujours en attente, nous ignorons simplement cette demande. Pour une exhaustivité, j'ai aussi ajouté des cachedvalues. Donc, si la demande d'Ajax était déjà faite, nous ne le refusons pas.
var ajaxRequestor = function ($) { "use strict"; //privates var cahedValues = {}; var currentAjaxRequest, callers; //public interface return { getData: function (callerId, onGet, onFail, forceRefresh) { if (forceRefresh || !cahedValues.myData) { //If there is a pending request, don't start new one if (!currentAjaxRequest || currentAjaxRequest.state() != "pending") { currentAjaxRequest = $.getJSON("data/MyData.json"); callers = {}; //list of callers waiting for request } //if this caller is not in the list, add it and queue up its callbacks to existing request if (!callers[callerId]) { callers.callerId = callerId; currentAjaxRequest.done(function (data, textStatus) { cahedValues.myData = data; onGet(data); }); currentAjaxRequest.fail(function (jqxhr, textStatus, error) { if (!!onFail) { onFail(error); } else throw error; }); } } else { onGet(cahedValues.myData); } }, invalidateMyData: function () { delete cahedValues.myData; } }; })($);