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 相关文章推荐
求解开jscript.encode代码的asp函数
Feb 28 Javascript
asp批量修改记录的代码
Jun 25 Javascript
JavaScript instanceof 的使用方法示例介绍
Oct 23 Javascript
javascript实现无缝上下滚动特效
Dec 16 Javascript
javascript实现随机生成DIV背景色
Jun 20 Javascript
JS之获取样式的简单实现方法(推荐)
Sep 13 Javascript
Bootstrap中glyphicons-halflings-regular.woff字体报404错notfound的解决方法
Jan 19 Javascript
JavaScript实现256色转灰度图
Feb 22 Javascript
基于Jquery Ajax type的4种类型(详解)
Aug 02 jQuery
浅谈Vuex的状态管理(全家桶)
Nov 04 Javascript
vue全局组件与局部组件使用方法详解
Mar 29 Javascript
vue 遮罩层阻止默认滚动事件操作
Jul 28 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 中的str_replace 函数总结
2007/04/27 PHP
php实现两表合并成新表并且有序排列的方法
2014/12/05 PHP
使用PHP处理数据库数据如何将数据返回客户端并显示当前状态
2016/02/16 PHP
YII框架模块化处理操作示例
2019/04/26 PHP
laravel5.5安装jwt-auth 生成token令牌的示例
2019/10/24 PHP
jQuery库与其他JS库冲突的解决办法
2010/02/07 Javascript
两个JavaScript jsFiddle JSBin在线调试器
2010/03/14 Javascript
javaScript checkbox 全选/反选及批量删除
2010/04/28 Javascript
从零开始学习jQuery (六) jquery中的AJAX使用
2011/02/23 Javascript
一些老手都不一定知道的JavaScript技巧
2014/05/06 Javascript
JavaScript获取路径设计源码
2014/05/22 Javascript
Angular实现form自动布局
2016/01/28 Javascript
JavaScript深度复制(deep clone)的实现方法
2016/02/19 Javascript
js生成随机数方法和实例
2017/01/17 Javascript
微信小程序实现流程进度的图样式功能
2018/01/16 Javascript
Vue 路由切换时页面内容没有重新加载的解决方法
2018/09/01 Javascript
vue2.0中set添加属性后视图不能更新的解决办法
2019/02/22 Javascript
微信公众号平台接口开发 菜单管理的实现
2019/08/14 Javascript
layui下拉框获取下拉值(select)的例子
2019/09/10 Javascript
python错误:AttributeError: 'module' object has no attribute 'setdefaultencoding'问题的解决方法
2014/08/22 Python
python实现合并两个数组的方法
2015/05/16 Python
Python处理JSON数据并生成条形图
2016/08/05 Python
基于python 二维数组及画图的实例详解
2018/04/03 Python
python opencv实现证件照换底功能
2019/08/19 Python
Python的in,is和id函数代码实例
2020/04/18 Python
python安装第三方库如xlrd的方法
2020/10/31 Python
css3实现针线缝合效果(图解步骤)
2013/02/04 HTML / CSS
HTML5 Plus 实现手机APP拍照或相册选择图片上传功能
2016/07/13 HTML / CSS
canvas实现圆形进度条动画的示例代码
2017/12/26 HTML / CSS
详解html5页面 rem 布局适配方法
2018/01/12 HTML / CSS
Gucci法国官方网站:意大利奢侈品牌
2018/07/25 全球购物
大学生物业管理求职信
2013/10/24 职场文书
资产经营总监岗位职责
2013/12/04 职场文书
党的群众路线教育实践活动个人对照检查材料
2014/09/22 职场文书
2015年银行员工工作总结
2015/04/24 职场文书
教您:房贷工资收入证明应该怎么写?
2019/08/19 职场文书