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极简入门教程(三):数组
Oct 25 Javascript
使用JS实现图片展示瀑布流效果的实例代码
Sep 12 Javascript
动态JavaScript所造成一些你不知道的危害
Sep 25 Javascript
js实现对table的增加行和删除行的操作方法
Oct 13 Javascript
封装运动框架实战左右与上下滑动的焦点轮播图(实例)
Oct 17 Javascript
小程序实现搜索界面 小程序实现推荐搜索列表效果
May 18 Javascript
基于Vue和Element-Ui搭建项目的方法
Sep 06 Javascript
原生js+ajax分页组件
Jan 30 Javascript
Vue脚手架编写试卷页面功能
Mar 17 Javascript
JavaScript设计模式---单例模式详解【四种基本形式】
May 16 Javascript
js实现查询商品案例
Jul 22 Javascript
js实现滑动进度条效果
Aug 21 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
vBulletin Forum 2.3.xx SQL Injection
2006/10/09 PHP
php中var_export与var_dump的区别分析
2010/08/21 PHP
php中json_encode中文编码问题分析
2011/09/13 PHP
深入PHP许愿墙模块功能分析
2013/06/25 PHP
PHP使用memcache缓存技术提高响应速度的方法
2014/12/26 PHP
PHP使用openssl扩展实现加解密方法示例
2020/02/20 PHP
extjs grid取到数据而不显示的解决
2008/12/29 Javascript
jsTree树控件(基于jQuery, 超强悍)[推荐]
2009/09/01 Javascript
javascript作用域容易记错的两个地方分析
2012/06/22 Javascript
JavaScript事件委托技术实例分析
2015/02/06 Javascript
jQuery语法小结(超实用)
2015/12/31 Javascript
不用一句js代码初始化组件
2016/01/27 Javascript
关于cookie的初识和运用(js和jq)
2016/04/07 Javascript
微信小程序实现瀑布流布局与无限加载的方法详解
2017/05/12 Javascript
vue实现表格增删改查效果的实例代码
2017/07/18 Javascript
详解vuex的简单使用
2018/03/12 Javascript
spirngmvc js传递复杂json参数到controller的实例
2018/03/29 Javascript
mpvue 如何使用腾讯视频插件的方法
2018/07/16 Javascript
JS的Ajax与后端交互数据的实例
2018/08/08 Javascript
vue实现公告栏文字上下滚动效果的示例代码
2020/06/16 Javascript
Vue如何提升首屏加载速度实例解析
2020/06/25 Javascript
python中实现定制类的特殊方法总结
2014/09/28 Python
想学python 这5本书籍你必看!
2018/12/11 Python
查看python安装路径及pip安装的包列表及路径
2019/04/03 Python
windows安装TensorFlow和Keras遇到的问题及其解决方法
2019/07/10 Python
python爬虫之遍历单个域名
2019/11/20 Python
python3 assert 断言的使用详解 (区别于python2)
2019/11/27 Python
解决Pytorch训练过程中loss不下降的问题
2020/01/02 Python
tensorflow保持每次训练结果一致的简单实现
2020/02/17 Python
Python使用Matlab命令过程解析
2020/06/04 Python
HTML5利用约束验证API来检查表单的输入数据的代码实例
2016/12/20 HTML / CSS
小摄影师教学反思
2014/04/27 职场文书
运动会广播稿200米(5篇)
2014/10/15 职场文书
男方婚前保证书
2015/02/28 职场文书
会议通知
2015/04/15 职场文书
Python安装使用Scrapy框架
2022/04/12 Python