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 相关文章推荐
拖动一个HTML元素
Dec 22 Javascript
关于JS字符串函数String.replace()
Apr 07 Javascript
jQuery之尺寸调整组件的深入解析
Jun 19 Javascript
jquery实现metro效果示例代码
Sep 06 Javascript
JS解析XML实例分析
Jan 30 Javascript
JavaScript焦点事件、鼠标事件和滚轮事件使用详解
Jan 15 Javascript
AngularJS基础 ng-readonly 指令简单示例
Aug 02 Javascript
Three.js开发实现3D地图的实践过程总结
Nov 20 Javascript
微信小程序的tab选项卡的实现效果
May 15 Javascript
vue $set 给数据赋值的实例
Nov 09 Javascript
JS实现前端路由功能示例【原生路由】
May 29 Javascript
理解Proxy及使用Proxy实现vue数据双向绑定操作
Jul 18 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
apache2.2.4+mysql5.0.77+php5.2.8安装精简
2009/04/29 PHP
PHP新手入门学习方法
2011/05/08 PHP
php在线代理转向代码
2012/05/05 PHP
ThinkPHP3.2框架自定义配置和加载用法示例
2018/06/14 PHP
用jQuery中的ajax分页实现代码
2011/09/20 Javascript
JavaScript高级程序设计阅读笔记(十六) javascript检测浏览器和操作系统-detect.js
2012/08/14 Javascript
Javascript图像处理—为矩阵添加常用方法
2012/12/27 Javascript
javascript基础之查找元素的详细介绍(访问节点)
2013/07/05 Javascript
js检查页面上有无重复id的实现代码
2013/07/17 Javascript
点击按钮或链接不跳转只刷新页面的脚本整理
2013/10/22 Javascript
jquery插件开发之实现google+圈子选择功能
2014/03/10 Javascript
jQuery修改CSS伪元素属性的方法
2014/07/30 Javascript
js构造函数、索引数组和属性的实现方式和使用
2014/11/16 Javascript
JavaScript 实现的checkbox经典实例分享
2016/10/16 Javascript
浅谈JavaScript事件绑定的常用方法及其优缺点分析
2016/11/01 Javascript
半个小时学json(json传递示例)
2016/12/25 Javascript
使用Angular缓存父页面数据的方法
2017/01/03 Javascript
Angular2开发——组件规划篇
2017/03/28 Javascript
正则表达式基本语法及表单验证操作详解【基于JS】
2017/04/07 Javascript
Bootstrap Table从零开始
2017/06/30 Javascript
Vue.js递归组件构建树形菜单
2017/12/24 Javascript
JS使用Prim算法和Kruskal算法实现最小生成树
2019/01/17 Javascript
微信小程序 wepy框架与iview-weapp的用法详解
2019/04/10 Javascript
element-ui树形控件后台返回的数据+生成组织树的工具类
2020/03/05 Javascript
基于javascript原生判断DOM是否加载完毕
2020/10/14 Javascript
解决python2.7用pip安装包时出现错误的问题
2017/01/23 Python
python2与python3的print及字符串格式化小结
2018/11/30 Python
Python enumerate函数功能与用法示例
2019/03/01 Python
Python实现使用request模块下载图片demo示例
2019/05/24 Python
Django 后台获取文件列表 InMemoryUploadedFile的例子
2019/08/07 Python
解决pycharm下pyuic工具使用的问题
2020/04/08 Python
pycharm + django跨域无提示的解决方法
2020/12/06 Python
计算机专业毕业生求职信分享
2013/12/24 职场文书
医生爱岗敬业演讲稿
2014/08/26 职场文书
上课迟到检讨书范文
2015/05/06 职场文书
SQL Server数据定义——模式与基本表操作
2021/04/05 SQL Server