En JavaScript , les appels de méthodes chaînés sont très populaires et les amis qui utilisent jQuery doivent en avoir une compréhension approfondie. Cette méthode est décrite plus en détail dans "Javascript Design Patterns". Pour implémenter des appels de méthodes en chaîne, il vous suffit de laisser les méthodes définies dans le prototype renvoyer des références aux objets d'instance qui appellent ces méthodes. Jetez un œil dans le livre This. code:
(fonction() {
fonction _$(els) {
this.elements = [];
pour (var i = 0, len = els.length; i < len; ++i) {
élément var = els[i];
if (type d'élément == 'string') {
element = document.getElementById(element);
}
this.elements.push(élément);
}
} ;
_$.prototype = {
chacun : fonction(fn) {
pour ( var i = 0, len = this.elements.length; i < len; ++i ) {
fn.call(ce, ceci.elements[i]);
}
rends ceci ;
},
setStyle : fonction (prop, val) {
this.each(fonction(el) {
el.style[prop] = val;
});
rends ceci ;
},
afficher : fonction() {
var ça = ceci;
this.each(fonction(el) {
that.setStyle('display', 'block');
});
rends ceci ;
},
addEvent : fonction (type, fn) {
var ajouter = fonction(el) {
si (window.addEventListener) {
el.addEventListener(type, fn, false);
}
sinon si (window.attachEvent) {
el.attachEvent('on'+type, fn);
}
} ;
this.each(fonction(el) {
ajouter(el);
});
rends ceci ;
}
} ;
fenêtre.$ = fonction() {
renvoie un nouveau _$(arguments);
} ;
})();
Comme vous pouvez le voir, chaque méthode se termine par "return this", qui transmet l'objet de la méthode appelante à la méthode suivante de la chaîne. Cependant, si les données que nous souhaitons exploiter sont obtenues via une requête asynchrone, comment maintenir la chaîne d'appels de méthode ? Dustin Diaz nous fournit un moyen d'assurer des appels de méthodes chaînés. Il est également l'un des auteurs du livre "Javascript Design Patterns".
Il a d'abord construit un objet Queue, à savoir :
Utilisez-le ensuite comme outil pour créer notre chaîne de files d’attente de méthodes asynchrones. Avec cet outil, il est facile de créer un plugin jQuery qui récupère le contenu du serveur et l'ajoute à un sélecteur.
De cette façon, nous pouvons obtenir le contenu de manière asynchrone et continuer notre chaîne d'appels.
$("<div/>")
.fetch('/server/navigation.html')
.addClass('colonne')
.appendTo('#side');
Consultez la page de démonstration pour voir l’effet.
Que faire s'il y a de nombreux éléments dans une file d'attente en attente d'une réponse côté serveur ? L'auteur a construit une telle méthode, à laquelle il convient de se référer :
De cette façon, nous pouvons l'appeler de la manière suivante :
fetchTweet(url).linkify().filterBadWords().appendTo('#status');
À ce stade, nous savons déjà comment implémenter le chaînage de méthodes asynchrones, mais certaines questions soulevées par certains commentaires au bas de « Chaînage de files d'attente de méthodes asynchrones en JavaScript » méritent réflexion. Le plug-in $.fn.fetch n'a besoin que d'ajouter le contenu renvoyé à l'élément. La file d'attente est-elle nécessaire ? De plus, $.fn.load dans jQuery peut être complètement implémenté si une seule fonction de rappel est utilisée dans Queue, elle peut être écrite comme ceci :
(fonction ($) {
$.fn.fetch = fonction (url) {
var file d'attente = nouvelle file d'attente ;
this.each(fonction() {
var el = ceci;
$.ajax({
URL : URL,
tapez : 'obtenir',
Type de données : 'json',
succès : fonction (resp) {
$(el).html(resp['text1']);
}
});
});
rends ceci ;
} ;
})(jQuery);
Je me demande ce que tu en penses ?
fonction fetchTweet(url) {
this.queue = nouvelle file d'attente ;
ceci.tweet = "" ;
var soi = ceci ;
ajax(url, fonction(resp) {
self.tweet = resp;
self.queue.flush(this);
});
}
fetchTweet.prototype = {
linkify : fonction() {
this.queue.add(function(self) {
self.tweet = self.tweet.replace(/b@(w{1,20}b/g, '$1');
});
rends ceci ;
},
filtreBadWords : fonction() {
this.queue.add(function(self) {
self.tweet = self.tweet.replace(/b(fuck|shit|piss)b/g, "");
});
rends ceci ;
},
appendTo : fonction (sélecteur) {
this.queue.add(function(self) {
$(self.tweet).appendTo(sélecteur);
});
rends ceci ;
}
} ;
(fonction ($) {
$.fn.fetch = fonction (url) {
var file d'attente = nouvelle file d'attente ;
this.each(fonction() {
var el = ceci;
queue.add(fonction(resp) {
$(el).html(resp);
});
});
$.ajax({
URL : URL,
Type de données : 'html',
succès : fonction (html) {
queue.flush(html);
}
});
rends ceci ;
} ;
})(jQuery);
fonction File d'attente() {
// stocke vos rappels
this._methods = [];
// garde une référence à votre réponse
this._response = null ;
// toutes les files d'attente démarrent sans être vidées
this._flushed = faux;
}
File d'attente.prototype = {
// ajoute des rappels à votre file d'attente
ajouter : fonction (fn) {
// si la file d'attente a été vidée, retourne immédiatement
si (this._flushed) {
fn(this._response);
// sinon on le met dans la file d'attente
} autre {
this._methods.push(fn);
}
},
flush : fonction (resp) {
// remarque : le flush n'arrive qu'une seule fois
si (this._flushed) {
retour;
}
// stocke votre réponse pour les appels suivants après flush()
this._response = resp;
// marque qu'il a été vidé
this._flushed = vrai;
// les déplace et les rappelle
tandis que (this._methods[0]) {
this._methods.shift()(resp);
}
}
} ;