JavaScript 异步方法队列链实现代码分析


Posted in Javascript onJune 05, 2010

在《javascript设计模式》中对这种方法作了比较详细的描述,实现方法的链式调用,只须让在原型中定义的方法都返回调用这些方法的实例对象的引用即可,看看书中的这段代码:

(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”结束,这就会将调用方法的对象传递给链上的下一个方法。但是,如果我们要操作的数据是通过异步请求来获得的,如何保持方法的链式调用呢?Dustin Diaz为我们提供了一种方法来保证方法的链式调用,他也是《javascript设计模式》一书的作者之一。
他首先构建了一个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); 
} 
} 
};

然后用它作为工具构建我们的异步方法队列链。有了这个工具,就可以很方便的构建一个从服务器端获取内容并将其附加到选择器中的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);

这样,我们就可以异步的获取内容,并继续我们的链式调用。
$("<div/>") 
.fetch('/server/navigation.html') 
.addClass('column') 
.appendTo('#side');

查看demo页看看效果。
如果一个队列中有很多项等待对服务器端的响应进行操作,该如何处置?作者构建了这样一个方法,值得参考:
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; 
} 
};

这样,我们就可以用下面的方式来调用:
fetchTweet(url).linkify().filterBadWords().appendTo('#status');

到此,我们已经知道了如何实现异步方法链式调用,但在《Asynchronous method queue chaining in JavaScript》底部的一些评论提出的一些问题,值得思考一下。插件$.fn.fetch中仅仅只需将返回的内容附加到元素之中,Queue是否必要?而且,jQuery中的$.fn.load完全可以实现,如果Queue中只用一个回调函数,完全可以这样来写:
(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);

不知你作如何感想?
Javascript 相关文章推荐
Javascript 鼠标移动上去 滑块跟随效果代码分享
Nov 23 Javascript
jquery弹窗插件colorbox绑定动态生成元素的方法
Jun 20 Javascript
jQuery实现拖拽页面元素并将其保存到cookie的方法
Jun 12 Javascript
利用jquery获取select下拉框的值
Nov 23 Javascript
Spring Boot+AngularJS+BootStrap实现进度条示例代码
Mar 02 Javascript
Node.js对MongoDB数据库实现模糊查询的方法
May 03 Javascript
Vue实例中生命周期created和mounted的区别详解
Aug 25 Javascript
vue使用drag与drop实现拖拽的示例代码
Sep 07 Javascript
JS开发中基本数据类型具体有哪几种
Oct 19 Javascript
JS集合set类的实现与使用方法示例
Feb 01 Javascript
Vue.js组件实现选项卡以及切换特效
Jul 24 Javascript
js实现弹幕飞机效果
Aug 27 Javascript
js 全兼容可高亮二级缓冲折叠菜单
Jun 04 #Javascript
JavaScript中使用replace结合正则实现replaceAll的效果
Jun 04 #Javascript
利用jquery操作select下拉列表框的代码
Jun 04 #Javascript
JavaScript 页面编码与浏览器类型判断代码
Jun 03 #Javascript
javascript cookie操作类的实现代码小结附使用方法
Jun 02 #Javascript
js操作select控件的几种方法
Jun 02 #Javascript
Jquery升级新版本后选择器的语法问题
Jun 02 #Javascript
You might like
总集篇&特番节目先行播出!《SAO Alicization War of Underworld》第2季度TV动画4月25日放送!
2020/03/06 日漫
解析PHP工厂模式的好处
2013/06/18 PHP
PHP房贷计算器实例代码,等额本息,等额本金
2017/04/01 PHP
thinkPHP5框架中widget的功能与用法详解
2018/06/11 PHP
获取页面高度,窗口高度,滚动条高度等参数值getPageSize,getPageScroll
2006/09/22 Javascript
用javascript实现兼容IE7的类库 IE7_0_9.zip提供下载
2007/08/08 Javascript
javascript void(0)的妙用
2009/10/21 Javascript
Jquery 扩展方法
2010/05/06 Javascript
基于Jquery的仿照flash放大图片效果代码
2011/03/16 Javascript
js复制到剪切板的实例方法
2013/06/28 Javascript
jquery中checkbox全选失效的解决方法
2014/12/26 Javascript
jQuery操作JSON的CRUD用法实例
2015/02/25 Javascript
jquery模拟进度条实现方法
2015/08/03 Javascript
在JavaScript的jQuery库中操作AJAX的方法讲解
2015/08/15 Javascript
酷! 不同风格页面布局幻灯片特效js实现
2021/02/19 Javascript
HTML5+jQuery实现搜索智能匹配功能
2017/03/24 jQuery
微信小程序tabbar不显示解决办法
2017/06/08 Javascript
Node.JS使用Sequelize操作MySQL的示例代码
2017/10/09 Javascript
AngularJS中scope的绑定策略实例分析
2017/10/30 Javascript
AngularJS实现的锚点楼层跳转功能示例
2018/01/02 Javascript
微信小程序实现折叠与展开文章功能
2018/06/12 Javascript
微信小程序自定义可滑动日历界面
2018/12/28 Javascript
微信小程序五子棋游戏AI实现方法【附demo源码下载】
2019/02/20 Javascript
vue中利用iscroll.js解决pc端滚动问题
2020/02/15 Javascript
Pytorch 定义MyDatasets实现多通道分别输入不同数据方式
2020/01/15 Python
解决tensorflow 释放图,删除变量问题
2020/06/23 Python
Python 常用日期处理 -- calendar 与 dateutil 模块的使用
2020/09/02 Python
matplotlib教程——强大的python作图工具库
2020/10/15 Python
Canvas制作的下雨动画的示例
2018/03/06 HTML / CSS
俄罗斯EPL钻石珠宝店:ЭПЛ
2019/10/22 全球购物
Myprotein西班牙官网:欧洲第一大运动营养品牌
2020/02/24 全球购物
管理部副部长岗位职责范文
2014/03/09 职场文书
幼儿园毕业致辞
2015/07/29 职场文书
创业方案:赚钱的烧烤店该怎样做?
2019/07/05 职场文书
阿里云服务器部署mongodb的详细过程
2021/09/04 MongoDB
Vue.js中v-for指令的用法介绍
2022/03/13 Vue.js