JavaScript 异步方法队列链实现代码分析

在《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);

不知你作如何感想?

(0)

相关推荐

  • JS实现队列的先进先出功能示例

    本文实例讲述了JS实现队列的先进先出功能.分享给大家供大家参考,具体如下: /** * [Queue] * @param {[Int]} size [队列大小] */ function Queue(size) { var list = []; //向队列中添加数据 this.push = function(data) { if (data==null) { return false; } //如果传递了size参数就设置了队列的大小 if (size != null && !isNaN(s

  • JavaScript队列、优先队列与循环队列

    队列是一种遵从先进先出(FIFO)原则的有序集合 队列在尾部添加新元素,从顶部移除元素 队列的理解 队列在我们生活中最常见的场景就是排队了 队列这个名字也已经很通俗易懂了 和栈很像,这不过队列是先入先出的数据结构 队列的前面是队头 队列的后面是队尾 出队从队头出 入队从队尾入 队列的创建 和栈类似,这里我就不就不啰嗦了 同样需要实现一些功能 这里我类比生活中的排队上厕所 向队列中添加元素(进入排队的队伍中) 移除队头元素(队伍最前面的人出队进入厕所) 查看队头元素(查看队伍最前面的人) 判断队列

  • javascript中利用数组实现的循环队列代码

    //循环队列 function CircleQueue(size){ this.initQueue(size); } CircleQueue.prototype = { //初始化队列 initQueue : function(size){ this.size = size; this.list = new Array(); this.capacity = size + 1; this.head = 0; this.tail = 0; }, //压入队列 enterQueue : functio

  • JavaScript队列的应用实例详解【经典数据结构】

    本文实例讲述了JavaScript队列的应用.分享给大家供大家参考,具体如下: 和前面介绍的栈相反,队列是一种先进先出的线性表,它只允许在表的一端进行插入,而在另一端进行删除.JavaScript自己提供了两个队列方法shift和push方法,分别是出队和入队,其原理就是将元素插入数组最后一个和删除第一个元素. 这里需要注意一点,就是unshift方法的效率比push的效率要低很多.因为它要将入队之前的数组全部往前移动一位.这里我们就不用代码再次演示了. 和线性表类似,队列也分为顺序队列和链队列

  • JavaScript数组的栈方法与队列方法详解

    数组(Array)和对象(Object)应该是JavaScript中使用最多也是最频繁的两种类型了,Array提供了很多常用的方法:栈方法.队列方法.重排序方法.操作方法.位置方法.迭代方法等等. 1.Array的栈方法 栈是一种LIFO(Last-In-First-Out,后进先出)的数据结构,也就是最新添加的项最早被移除.栈中项的插入(push)和移除,只发生在一个位置--栈的顶部.ECMAScript为数组提供了push()和pop()方法,可以实现类似栈的行为.下面两图分别演示了入栈与出

  • JavaScript数据结构学习之数组、栈与队列

    前言 数据结构就是关系,没错,就是数据元素相互之间存在的一种或多种特定关系的集合. 常用的数据结构有: 数组,队列(queue),堆(heap),栈(stack),链表(linked list ),树(tree),图(graph)和散列表(hash) 本文主要介绍的是数组.栈与队列,下面来一起看看详细的介绍吧. 一.数组 数组是平时使用最常用的数据结构,在JavaScript中数组是动态的分配大小,在这里我不会介绍JavaScript里面数组的所有的方法,而是针对数据结构这个方向谈谈所用到的方法

  • JS实现队列与堆栈的方法

    本文实例讲述了JS实现队列与堆栈的方法.分享给大家供大家参考,具体如下: 在面向对象的程序设计里,一般都提供了实现队列(queue)和堆栈(stack)的方法,而对于JS来说,我们可以实现数组的相关操作,来实现队列和堆栈的功能,看下面的相关介绍. 一.看一下它们的性质,这种性质决定了它们的使用场合 队列:是一种支持先进先出(FIFO)的集合,即先被插入的数据,先被取出! 堆栈:是一种支持后进先出(LIFO)的集合,即后被插入的数据,先被取出! 二.看一下实现的代码(JS代码) var a=new

  • 自己封装的javascript事件队列函数版

    背景 javascript中使用addEventListener()或attachEvent()绑定事件时会有几个小问题: 一.使用addEventListener()或attachEvent()添加的匿名函数无法移除. 复制代码 代码如下: var oBtn = document.getElementById('btn'); oBtn.addEventListener('click',function(){    alert('button is clicked')},false) oBtn.

  • 深入JavaScript高级程序设计之对象、数组(栈方法,队列方法,重排序方法,迭代方法)

    继承是OO语言中的一个最为人津津乐道的概念. 许多OO语言都支持两种继承方式:接口继承和实现继承. 接口继承只继承方法签名,而实现继承则继承实际的方法. 如其所述,由于函数没有签名,在ECMAScript中无法实现接口继承. ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现的. 1.使用对象字面量定义对象 var person={}; 使用这种方式创建对象时,实际上不会调用Object构造函数. 开发人员更喜欢对象字面量的语法. 2.有时候需要传递大量可选参数的情形时,一

  • JavaScript数组实现数据结构中的队列与堆栈

    一.队列和堆栈的简单介绍 1.1.队列的基本概念 队列:是一种支持先进先出(FIFO)的集合,即先被插入的数据,先被取出! 如下图所示: 1.2.堆栈的基本概念 堆栈:是一种支持后进先出(LIFO)的集合,即后被插入的数据,先被取出! 如下图所示: 二. 在JavaScript中实现队列和堆栈 在JavaScript中实现队列和数组主要是通过数组,js数组中提供了以下几个方法可以让我们很方便实现队列和堆栈: •shift:从数组中把第一个元素删除,并返回这个元素的值. •unshift: 在数组

  • JavaScript数据结构与算法之栈与队列

    学习起因 曾经有一次在逛V2EX时,碰到这么一个帖子. 数学完全还给老师了,想学回一些基础数学,大概是高中程度的,有什么书籍推荐? 发帖的楼主大学没有高数课程,出去工作时一直在从事前端的工作.感觉到数学知识的匮乏,所以想补一补数学. 看了看帖子,感觉和我很像,因为我的专业是不开高数的,我学的也是前端.也同样感觉到了数学知识匮乏所带来的困顿.同时因为自己的数学思维实在是不怎么好,所以决定努力补习数学与计算机基础知识. 当时也有人说:"前端需要什么数据结构与算法",但是对于这个事情我有自己

  • js下写一个事件队列操作函数

    前两天在网上看到这一系列的文章<写一个JavaScript异步调用框架1,2,3,4,5,6>. 异步操作可能会产生你不希望的事件触发顺序.这个问题以前也遇到过,当时没想太多,也就是直接多层嵌套(在ajax返回以后嵌套下一个事件)来解决. 认真的看了一遍.看的头昏,不得不说我可能基础并不好,在大局上的掌握也不好.d反正我是觉得很难理解,也不觉得它的调用时够方便的. 如果是这么调用: var chain = Async.go(0); chain .next(function(){setTimeo

随机推荐