JavaScript 에서는 체인 메서드 호출이 매우 널리 사용되며 jQuery를 사용하는 친구는 이에 대해 깊이 이해해야 합니다. 이 메소드는 "Javascript 디자인 패턴"에 자세히 설명되어 있습니다. 메소드 체인 호출을 구현하려면 프로토타입에 정의된 메소드가 해당 메소드를 호출하는 인스턴스 객체에 대한 참조를 반환하도록 하기만 하면 됩니다. 암호:
(기능() {
함수 _$(els) {
this.elements = [];
for (var i = 0, len = els.length; i < len; ++i) {
var 요소 = els[i];
if (요소 유형 == '문자열') {
요소 = document.getElementById(요소);
}
this.elements.push(요소);
}
};
_$.prototype = {
각각: 함수(fn) {
for ( var i = 0, len = this.elements.length; i < len; ++i ) {
fn.call(this, this.elements[i]);
}
이거 돌려줘;
},
setStyle: 함수(prop, val) {
this.each(함수(el) {
el.style[prop] = 발;
});
이거 돌려줘;
},
표시: 함수() {
var = 이것;
this.each(함수(el) {
that.setStyle('display', 'block');
});
이거 돌려줘;
},
addEvent: 함수(유형, fn) {
var 추가 = 함수(el) {
if (window.addEventListener) {
el.addEventListener(type, fn, false);
}
else if (window.attachEvent) {
el.attachEvent('on'+type, fn);
}
};
this.each(함수(el) {
추가(엘);
});
이거 돌려줘;
}
};
window.$ = 함수() {
새로운 _$(인수) 반환;
};
})();
보시다시피, 각 메소드는 호출 메소드의 객체를 체인의 다음 메소드에 전달하는 "return this"로 끝납니다. 그러나 우리가 조작하려는 데이터가 비동기 요청을 통해 얻은 경우 메소드 호출 체인을 어떻게 유지합니까? Dustin Diaz는 체인 메서드 호출을 보장하는 방법을 제공하며 "Javascript Design Patterns"라는 책의 저자이기도 합니다.
그는 먼저 Queue 개체를 구성했습니다.
그런 다음 이를 비동기 메서드 대기열 체인을 구축하는 도구로 사용합니다. 이 도구를 사용하면 서버에서 콘텐츠를 가져와 선택기에 추가하는 jQuery 플러그인을 쉽게 구축할 수 있습니다.
이러한 방식으로 콘텐츠를 비동기적으로 가져오고 호출 체인을 계속할 수 있습니다.
$("<div/>")
.fetch('/server/navigation.html')
.addClass('열')
.appendTo('#side');
효과를 보려면 데모 페이지를 확인하세요.
서버 측 응답에 대한 조치를 기다리는 항목이 대기열에 많이 있는 경우 어떻게 해야 합니까? 저자는 다음과 같은 방법을 참고할 가치가 있는 방법을 구성했습니다.
이런 식으로 다음과 같이 호출할 수 있습니다.
fetchTweet(url).linkify().filterBadWords().appendTo('#status');
이 시점에서 우리는 비동기식 메소드 체이닝을 구현하는 방법을 이미 알고 있지만 " JavaScript의 비동기식 메소드 큐 체이닝 " 하단에 있는 일부 주석에서 제기된 몇 가지 질문은 생각해 볼 가치가 있습니다. 플러그인 $.fn.fetch는 반환된 콘텐츠를 요소에 추가하기만 하면 됩니다. Queue가 필요합니까? 또한 jQuery의 $.fn.load는 완전히 구현될 수 있습니다. Queue에서 하나의 콜백 함수만 사용하는 경우 다음과 같이 작성할 수 있습니다.
(함수($) {
$.fn.fetch = 함수(url) {
var 대기열 = 새 대기열;
this.each(함수() {
var 엘 = 이것;
$.아약스({
URL: URL,
유형: '가져오기',
데이터 유형: 'json',
성공: 함수(resp) {
$(el).html(resp['text1']);
}
});
});
이거 돌려줘;
};
})(jQuery);
당신은 어떻게 생각하는지 궁금해요?
함수 fetchTweet(url) {
this.queue = 새 대기열;
this.tweet = "";
var 자기 = 이것;
아약스(url, function(resp)) {
self.tweet = resp;
self.queue.flush(this);
});
}
fetchTweet.prototype = {
연결: 함수() {
this.queue.add(함수(self) {
self.tweet = self.tweet.replace(/b@(w{1,20}b/g, '$1');
});
이거 돌려줘;
},
filterBadWords: 함수() {
this.queue.add(함수(self) {
self.tweet = self.tweet.replace(/b(fuck|shit|piss)b/g, "");
});
이거 돌려줘;
},
AppendTo: 함수(선택기) {
this.queue.add(함수(self) {
$(self.tweet).appendTo(선택자);
});
이거 돌려줘;
}
};
(함수($) {
$.fn.fetch = 함수(url) {
var 대기열 = 새 대기열;
this.each(함수() {
var 엘 = 이것;
queue.add(함수(resp) {
$(el).html(resp);
});
});
$.아약스({
URL: URL,
데이터 유형: 'html',
성공: 함수(html) {
queue.flush(html);
}
});
이거 돌려줘;
};
})(jQuery);
함수 대기열() {
// 콜백 저장
this._methods = [];
// 응답에 대한 참조를 유지합니다.
this._response = null;
// 모든 대기열은 플러시되지 않은 채 시작됩니다.
this._flushed = false;
}
대기열.프로토타입 = {
// 대기열에 콜백을 추가합니다.
추가: 함수(fn) {
// 큐가 플러시된 경우 즉시 반환
if (this._flush) {
fn(this._response);
// 그렇지 않으면 대기열에 푸시합니다.
} 또 다른 {
this._methods.push(fn);
}
},
플러시: 함수(resp) {
// 참고: 플러시는 한 번만 발생합니다.
if (this._flush) {
반품;
}
// 플러시() 이후 후속 호출에 대한 응답을 저장합니다.
this._response = resp;
// 플러시되었음을 표시
this._flushed = true;
// 그들을 밖으로 이동시키고 다시 호출합니다.
동안 (this._methods[0]) {
this._methods.shift()(resp);
}
}
};