Em JavaScript , as chamadas de métodos encadeados são muito populares e os amigos que usam jQuery devem ter um conhecimento profundo disso. Este método é descrito com mais detalhes em "Javascript Design Patterns". Para implementar chamadas em cadeia de métodos, você só precisa deixar os métodos definidos no protótipo retornarem referências aos objetos de instância que chamam esses métodos. código:
(função() {
função _$(els) {
isto.elementos = [];
for (var i = 0, len = els.length; i < len; ++i) {
var elemento = els[i];
if (typeof elemento == 'string') {
elemento = document.getElementById(elemento);
}
this.elements.push(elemento);
}
};
_$.protótipo = {
cada: function(fn) {
for ( var i = 0, len = this.elements.length; i < len; ++i ) {
fn.call(este, este.elementos[i]);
}
devolva isso;
},
setStyle: função(prop, val) {
this.each(função(el) {
el.style[prop] = val;
});
devolva isso;
},
mostrar: função() {
var isso = isso;
this.each(função(el) {
that.setStyle('display', 'bloquear');
});
devolva isso;
},
addEvent: função(tipo, fn) {
var adicionar = função(el) {
if (window.addEventListener) {
el.addEventListener(tipo,fn,falso);
}
senão if (window.attachEvent) {
el.attachEvent('on'+type, fn);
}
};
this.each(função(el) {
adicionar(el);
});
devolva isso;
}
};
janela.$ = função() {
retornar novo _$(argumentos);
};
})();
Como você pode ver, cada método termina com “return this”, que passa o objeto do método chamador para o próximo método na cadeia. Porém, se os dados que queremos operar são obtidos por meio de uma solicitação assíncrona, como manter a cadeia de chamadas de método? Dustin Diaz nos fornece uma maneira de garantir chamadas de métodos encadeados. Ele também é um dos autores do livro "Javascript Design Patterns".
Ele primeiro construiu um objeto Queue, a saber:
Em seguida, use-o como uma ferramenta para construir nossa cadeia de filas de métodos assíncronos. Com esta ferramenta, é fácil construir um plugin jQuery que busca conteúdo do servidor e o anexa a um seletor.
Dessa forma, podemos obter o conteúdo de forma assíncrona e continuar nossa cadeia de chamadas.
$("<div/>")
.fetch('/server/navigation.html')
.addClass('coluna')
.appendTo('#lado');
Confira a página de demonstração para ver o efeito.
O que fazer se houver muitos itens em uma fila aguardando resposta do lado do servidor? O autor construiu tal método, ao qual vale a pena referir:
Desta forma, podemos chamá-lo da seguinte forma:
fetchTweet(url).linkify().filterBadWords().appendTo('#status');
Neste ponto, já sabemos como implementar o encadeamento de métodos assíncronos, mas vale a pena pensar em algumas questões levantadas por alguns comentários na parte inferior de " Encadeamento de filas de métodos assíncronos em JavaScript ". O plug-in $.fn.fetch só precisa anexar o conteúdo retornado ao elemento. A fila é necessária? Além disso, $.fn.load em jQuery pode ser completamente implementado. Se apenas uma função de retorno de chamada for usada no Queue, ela pode ser escrita assim:
(função($){
$.fn.fetch=função(url){
var fila = nova fila;
this.each(função() {
var el = isto;
$.ajax({
url: url,
digite: 'obter',
tipo de dados: 'json',
sucesso: função(resp) {
$(el).html(resp['text1']);
}
});
});
devolva isso;
};
})(jQuery);
Eu me pergunto o que você acha?
função buscarTweet(url) {
this.queue = nova fila;
este.tweet = "";
var self = isto;
ajax(url, função(resp) {
self.tweet = resp;
self.queue.flush(isto);
});
}
fetchTweet.prototype = {
vincular: function() {
this.queue.add(function(self) {
self.tweet = self.tweet.replace(/b@(w{1,20}b/g, '$1');
});
devolva isso;
},
filterBadWords: function() {
this.queue.add(function(self) {
self.tweet = self.tweet.replace(/b(porra|merda|mijo)b/g, "");
});
devolva isso;
},
anexarTo: function(seletor) {
this.queue.add(function(self) {
$(self.tweet).appendTo(seletor);
});
devolva isso;
}
};
(função($){
$.fn.fetch=função(url){
var fila = nova fila;
this.each(função() {
var el = isto;
fila.add(função(resp) {
$(el).html(resp);
});
});
$.ajax({
url: url,
tipo de dados: 'html',
sucesso: função(html) {
fila.flush(html);
}
});
devolva isso;
};
})(jQuery);
function Fila() {
//armazena seus retornos de chamada
this._methods = [];
// mantém uma referência para sua resposta
this._response = null;
// todas as filas começam sem liberação
this._flushed = falso;
}
Queue.prototype = {
//adiciona retornos de chamada à sua fila
adicione: função(fn) {
// se a fila foi liberada, retorna imediatamente
if (this._flushed) {
fn(this._response);
// caso contrário, coloque-o na fila
} outro {
this._methods.push(fn);
}
},
liberar: função(resp) {
// nota: flush só acontece uma vez
if (this._flushed) {
retornar;
}
// armazena sua resposta para chamadas subsequentes após flush()
this._response = resp;
// marca que foi liberado
this._flushed = verdadeiro;
// tira-os e chama-os de volta
enquanto (this._methods[0]) {
this._methods.shift()(resp);
}
}
};