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----文件操作
Jan 18 Javascript
深入理解JavaScript系列(14) 作用域链介绍(Scope Chain)
Apr 12 Javascript
Javascript中查找不以XX字符结尾的单词示例代码
Oct 15 Javascript
简单的邮箱登陆的提示效果类似于yahoo邮箱
Feb 26 Javascript
jfinal与bootstrap的登录跳转实战演习
Sep 22 Javascript
js实现常用排序算法
Aug 09 Javascript
JavaScript里 ==与===区别详解
Aug 16 Javascript
原生JavaScript实现AJAX、JSONP
Feb 07 Javascript
jQuery实现链接的title快速出现的方法
Feb 20 Javascript
详解Angular.js指令中scope类型的几种特殊情况
Feb 21 Javascript
在vue使用clipboard.js进行一键复制文本的实现示例
Jan 15 Javascript
angular 实现同步验证器跨字段验证的方法
Apr 11 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 PDOStatement:bindParam插入数据错误问题分析
2013/11/13 PHP
写一段简单的PHP建立文件夹代码
2015/01/06 PHP
浅谈COOKIE和SESSION区别
2015/07/19 PHP
浅谈thinkphp5 instance 的简单实现
2017/07/30 PHP
详解php中生成标准uuid(guid)的方法
2019/04/28 PHP
Laravel6.2中用于用户登录的新密码确认流程详解
2019/10/16 PHP
需要做特殊处理的DOM元素属性的访问
2010/11/05 Javascript
根据一段代码浅谈Javascript闭包
2010/12/14 Javascript
jQuery ajax serialize()方法的使用以及常见问题解决
2013/01/27 Javascript
JQGrid的用法解析(列编辑,添加行,删除行)
2013/11/08 Javascript
javascript放大镜效果的简单实现
2013/12/09 Javascript
JQEasy-ui在IE9以下版本中二次加载的问题分析及处理方法
2014/06/23 Javascript
Jquery api 速查表分享
2015/01/12 Javascript
JS判断当前页面是否在微信浏览器打开的方法
2015/12/08 Javascript
基于jQuery实现顶部导航栏功能
2016/12/27 Javascript
jQuery实现限制文本框的输入长度
2017/01/11 Javascript
Vue-cli@3.0 插件系统简析
2018/09/05 Javascript
vue使用openlayers实现移动点动画
2020/09/24 Javascript
微信小程序实现单个或多个倒计时功能
2020/11/01 Javascript
Python 字符串定义
2009/09/25 Python
python requests 使用快速入门
2017/08/31 Python
python中 logging的使用详解
2017/10/25 Python
Python中使用支持向量机(SVM)算法
2017/12/26 Python
在pycharm中python切换解释器失败的解决方法
2018/10/29 Python
python+mysql实现教务管理系统
2019/02/20 Python
关于PyTorch源码解读之torchvision.models
2019/08/17 Python
PyCharm2018 安装及破解方法实现步骤
2019/09/09 Python
Ubuntu下Python+Flask分分钟搭建自己的服务器教程
2019/11/19 Python
解决安装新版PyQt5、PyQT5-tool后打不开并Designer.exe提示no Qt platform plugin的问题
2020/04/24 Python
Python结合Window计划任务监测邮件的示例代码
2020/08/05 Python
如何基于pandas读取csv后合并两个股票
2020/09/25 Python
优秀教研组申报材料
2014/12/26 职场文书
金砖之国观后感
2015/06/11 职场文书
2015年行政管理人员工作总结
2015/10/15 职场文书
为什么代码规范要求SQL语句不要过多的join
2021/06/23 MySQL
java版 联机五子棋游戏
2022/05/04 Java/Android