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 相关文章推荐
jquery $.ajax入门应用二
Nov 19 Javascript
jquery tools之tabs 选项卡/页签
Jul 25 Javascript
关于页面嵌入swf覆盖div层的问题的解决方法
Feb 11 Javascript
使用GruntJS构建Web程序之合并压缩篇
Jun 06 Javascript
node.js中的fs.lchmod方法使用说明
Dec 16 Javascript
解决ueditor jquery javascript 取值问题
Dec 30 Javascript
jQuery表单域选择器用法分析
Feb 10 Javascript
JavaScript数据类型之基本类型和引用类型的值
Apr 01 Javascript
JavaScript实现下拉列表框数据增加、删除、上下排序的方法
Aug 11 Javascript
Vue2仿淘宝实现省市区三级联动
Apr 15 Javascript
小程序点赞收藏功能的实现代码示例
Sep 07 Javascript
es6 filter() 数组过滤方法总结
Apr 03 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
PHP连接SQLServer2005方法及代码
2013/12/26 PHP
PHP超牛逼无限极分类生成树方法
2015/05/11 PHP
PHP结合Ueditor并修改图片上传路径
2016/10/16 PHP
php实现等比例压缩图片
2018/07/26 PHP
一段实时更新的时间代码
2006/07/07 Javascript
jQuery选择没有colspan属性的td的代码
2010/07/06 Javascript
IE 当eval遇上function的处理
2011/08/09 Javascript
JS实现表单中checkbox对勾选中增加边框显示效果
2015/08/21 Javascript
jQuery实现伪分页的方法分享
2016/02/17 Javascript
微信小程序 火车票查询实例讲解
2016/10/17 Javascript
JS ES6多行字符串与连接字符串的表示方法
2017/04/26 Javascript
详解vue 数据传递的方法
2018/04/19 Javascript
微信小程序学习笔记之函数定义、页面渲染图文详解
2019/03/28 Javascript
pygame学习笔记(6):完成一个简单的游戏
2015/04/15 Python
详解Python编程中基本的数学计算使用
2016/02/04 Python
python3 实现的人人影视网站自动签到
2016/06/19 Python
python2和python3的输入和输出区别介绍
2018/11/20 Python
Python实现的删除重复文件或图片功能示例【去重】
2019/04/23 Python
Python基础学习之基本数据结构详解【数字、字符串、列表、元组、集合、字典】
2019/06/18 Python
Python爬虫 urllib2的使用方法详解
2019/09/23 Python
常用python爬虫库介绍与简要说明
2020/01/25 Python
Django实现whoosh搜索引擎使用jieba分词
2020/04/08 Python
pip 20.3 新版本发布!即将抛弃 Python 2.x(推荐)
2020/12/16 Python
四个太阳教学反思
2014/02/01 职场文书
北京申奥口号
2014/06/19 职场文书
2015年林业工作总结
2015/05/14 职场文书
聋哑人盗窃罪辩护词
2015/05/21 职场文书
敬老院活动感想
2015/08/07 职场文书
培训心得体会怎么写
2016/01/25 职场文书
美甲店的创业计划书模板
2019/08/23 职场文书
使用 JavaScript 制作页面效果
2021/04/21 Javascript
vue组件的路由高亮问题解决方法
2021/05/11 Vue.js
Python实现简繁体转换
2021/06/07 Python
mysq启动失败问题及场景分析
2021/07/15 MySQL
Java 超详细讲解IO操作字节流与字符流
2022/03/25 Java/Android
AJAX引擎原理以及XmlHttpRequest对象的axios、fetch区别详解
2022/04/09 Javascript