在javascript中,方法的鏈?zhǔn)秸{(diào)用很流行,使用jQuery的朋友對此一定深有體會。在《javascript設(shè)計模式》中對這種方法作了比較詳細(xì)的描述,實現(xiàn)方法的鏈?zhǔn)秸{(diào)用,只須讓在原型中定義的方法都返回調(diào)用這些方法的實例對象的引用即可,看看書中的這段代碼:
(function() { function _$(els) { this.elements = []; for (var i = 0, len = els.length; i < len; ++i) { var element = els[i]; if (typeof element == 'string') { element = document.getElementById(element); } this.elements.push(element); } }; _$.prototype = { each: function(fn) { for ( var i = 0, len = this.elements.length; i < len; ++i ) { fn.call(this, this.elements[i]); } return this; }, setStyle: function(prop, val) { this.each(function(el) { el.style[prop] = val; }); return this; }, show: function() { var that = this; this.each(function(el) { that.setStyle('display', 'block'); }); return this; }, addEvent: function(type, fn) { var add = function(el) { if (window.addEventListener) { el.addEventListener(type, fn, false); } else if (window.attachEvent) { el.attachEvent('on'+type, fn); } }; this.each(function(el) { add(el); }); return this; } }; window.$ = function() { return new _$(arguments); }; })();
可以看到,每個方法都以”return this”結(jié)束,這就會將調(diào)用方法的對象傳遞給鏈上的下一個方法。但是,如果我們要操作的數(shù)據(jù)是通過異步請求來獲得的,如何保持方法的鏈?zhǔn)秸{(diào)用呢?Dustin Diaz為我們提供了一種方法來保證方法的鏈?zhǔn)秸{(diào)用,他也是《javascript設(shè)計模式》一書的作者之一。
他首先構(gòu)建了一個Queue對象,即:
function Queue() { // store your callbacks this._methods = []; // keep a reference to your response this._response = null; // all queues start off unflushed this._flushed = false; }
Queue.prototype = { // adds callbacks to your queue add: function(fn) { // if the queue had been flushed, return immediately if (this._flushed) { fn(this._response);
// otherwise push it on the queue } else { this._methods.push(fn); } },
flush: function(resp) { // note: flush only ever happens once if (this._flushed) { return; } // store your response for subsequent calls after flush() this._response = resp; // mark that it's been flushed this._flushed = true; // shift 'em out and call 'em back while (this._methods[0]) { this._methods.shift()(resp); } } };
然后用它作為工具構(gòu)建我們的異步方法隊列鏈。有了這個工具,就可以很方便的構(gòu)建一個從服務(wù)器端獲取內(nèi)容并將其附加到選擇器中的jQuery plugin。
(function($) {
$.fn.fetch = function(url) { var queue = new Queue; this.each(function() { var el = this; queue.add(function(resp) { $(el).html(resp); }); });
$.ajax({ url: url, dataType: 'html', success: function(html) { queue.flush(html); } }); return this; };
})(jQuery);
這樣,我們就可以異步的獲取內(nèi)容,并繼續(xù)我們的鏈?zhǔn)秸{(diào)用。
$("<div/>") .fetch('/server/navigation.html') .addClass('column') .appendTo('#side');
查看demo頁看看效果。
如果一個隊列中有很多項等待對服務(wù)器端的響應(yīng)進(jìn)行操作,該如何處置?作者構(gòu)建了這樣一個方法,值得參考:
function fetchTweet(url) { this.queue = new Queue; this.tweet = ""; var self = this; ajax(url, function(resp) { self.tweet = resp; self.queue.flush(this); }); } fetchTweet.prototype = {
linkify: function() { this.queue.add(function(self) { self.tweet = self.tweet.replace(/\b@(\w{1,20}\b/g, '$1'); }); return this; },
filterBadWords: function() { this.queue.add(function(self) { self.tweet = self.tweet.replace(/\b(fuck|shit|piss)\b/g, ""); }); return this; },
appendTo: function(selector) { this.queue.add(function(self) { $(self.tweet).appendTo(selector); }); return this; }
};
這樣,我們就可以用下面的方式來調(diào)用:
fetchTweet(url).linkify().filterBadWords().appendTo('#status');
到此,我們已經(jīng)知道了如何實現(xiàn)異步方法鏈?zhǔn)秸{(diào)用,但在《Asynchronous method queue chaining in JavaScript》底部的一些評論提出的一些問題,值得思考一下。插件$.fn.fetch中僅僅只需將返回的內(nèi)容附加到元素之中,Queue是否必要?而且,jQuery中的$.fn.load完全可以實現(xiàn),如果Queue中只用一個回調(diào)函數(shù),完全可以這樣來寫:
(function($) { $.fn.fetch = function(url) { var queue = new Queue; this.each(function() { var el = this; $.ajax({ url: url, type: 'get', dataType: 'json', success: function(resp) { $(el).html(resp['text1']); } }); }); return this; };
})(jQuery);
不知你作如何感想?
原文:http://www.dustindiaz.com/async-method-queues/ 譯文:http://www.denisdeng.com/?p=978
本文鏈接:http://www.95time.cn/tech/web/2010/7605.asp
出處:
責(zé)任編輯:bluehearts
◎進(jìn)入論壇網(wǎng)頁制作、WEB標(biāo)準(zhǔn)化版塊參加討論,我還想發(fā)表評論。
|