您的位置:首页 > Web前端 > JQuery

定时炸弹--JQuery中的Deferred对象

2012-07-04 14:15 295 查看
从1.5开始,JQuery引入了Deferred对象,应用这个对象,针对一个行为可以注册多个回调函数,并能将行为的调用结果进行传递。以下用一些例子来说明这个对象的强大功能。

楔子:


以下的代码是用来获取一个文件的内容,获取完毕后弹出文件的内容。

<html>

<head>

<title></title>

<script
type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>

</head>

<body>

<script
type="text/javascript" language="javascript">

$(function () {

$.get(

"content.txt",

function (resp) {

alert(resp);

}

);

});

</script>

</body>

</html>

执行结果如下:



1. 延迟调用


以上的这段程序,如果我不想马上执行,而是想在这里注册一下,在将来的某个时候让他执行。如果用传统的方法很难实现,这里Deferred的对象的优势就显示出来了。请看下面的代码:

var deferred = $.Deferred();

deferred.done(function () {

$.get(

"content.txt",

function (resp) {

alert(resp);

}

);

});

alert("other things...")

deferred.resolve();

上面的代码中,我先将要执行的代码写上,然后去做其他的事情。等到我想要这段代码执行的时候,只要调用 deferred.resolve();就可以了。

当然,也可以将这个deferred对象做为参数传递到其他地方,在其他地方调用deferred.resolve()来让这段代码执行。

我们可以把Deferred对象想象成一颗定时炸弹,把它埋在一个地方,以后我们想让它爆炸的时候,只要调用一下deferred.resolve()。

2. deferred.reject


deferred.reject与deferred.resolve正好相反,后者是让指定的行为正常执行,而前者将指定的行为拒绝,不让它执行。请看下面的代码:

var deferred = $.Deferred();

deferred.then(function () {

$.get(

"content.txt",

function (resp) {

alert(resp);

}

);

},

function () {

alert("failed");

}

);

//alert("other things...")

deferred.reject();

执行的结果是弹出failed.

可以看出,reject以后,会发送到failCallbacks回调函数中。

3. deferred.done()和deferred.then()


deferred.done()和deferred.then()都是在Deferred对象被Resolve或者rejected的时候调用的。请看下面的代码:

var deferred = $.Deferred();

deferred.done(function () {

alert("done");

});

deferred.then(function () {

alert("then");

});

deferred.resolve();

执行结果是先弹出done,后弹出then.

如果我们把done和then的顺序调换一下:

var deferred = $.Deferred();

deferred.then(function () {

alert("then");

});

deferred.done(function () {

alert("done");

});

deferred.resolve();

这次的执行结果就是先弹出then,后弹出done。

看来deferred.then()和deferred.then()谁放在前面谁先执行。

deferred.done()和deferred.then()都可以附加多个回调函数,请看下面的代码(注意中括号的使用):

function doneFunc1() {

alert("doneFunc1");

}

function doneFunc2() {

alert("doneFunc2");

}

function thenFunc1() {

alert("thenFunc1");

}

function thenFunc2() {

alert("thenFunc2");

}

var deferred = $.Deferred();

deferred.then([thenFunc1,thenFunc2]);

deferred.done([doneFunc1,doneFunc2]);

deferred.resolve();

deferred.done()和deferred.then()两者的用法很相似,唯一的区别就是参数不同:

deferred.then( doneCallbacks, failCallbacks )

deferred.done( doneCallbacks [, doneCallbacks] )

从函数定义可以看出,deferred.then()可以添加FailCallBack,而deferred.done不能。

4. deferred.fail


deferred.fail用来添加一个处理事件,该处理事件在Deferred对象被reject时执行。请看下面的例子:

var deferred = $.Deferred();

deferred.fail(function () {

alert("fail!");

});

deferred.reject();

5. deferred.always


deferred.done()和deferred.then()在deferred对象的行为成功时执行,deferred.fail在deferred对象的行为失败时执行,而deferred.always则在所有的时候都执行。

用这四个函数,我们可以模拟传统编程中的try,catch, finally.请看下面的例子:

var deferred = $.Deferred();

deferred.done(function () {

alert("try 1");

});

deferred.then(function () {

alert("try 2");

});

deferred.fail(function () {

alert("catch");

});

deferred.always(function () {

alert("finally");

});

以上的代码,当我们分别调用deferred.resolve()和deferred.reject()时,会看到与try,catch,finally同样的效果。

6. deferred.notify


deferred.resolve和deferred.reject都属于终结性的行为,也就是说,调用了deferred.resolve和deferred.reject后,再也不能对deferred对象进行状态上的改变(resolve, reject, notify, resolveWith, rejectWith, 和 notifyWith)。下面的例子中,第二个reject不会执行。

var deferred = $.Deferred();

deferred.done(function () {

alert("done");

});

deferred.fail(function () {

alert("fail");

});

deferred.resolve();

deferred.reject();

如果我们想让deferred对象做一些事情,而又不想终结该deferred对象,该怎么办哪?这就是deferred.notify方法的作用。请看下面的例子:

var deferred = $.Deferred();

deferred.progress(function (args) {

alert(args);

});

deferred.notify("notify1");

deferred.notify("notify2");

deferred.resolve();

这个例子的执行结果会依次弹出notify1和notify2.

7. deferred.progress


deferred.progress方法在第6条的例子中已经见到过,它就是和deferred.notify配对使用。

8. deferred.promise


有这样一种情况:我们暴露出一个Deferred对象给其他函数使用,但是只想让用户向上面挂回调函数,不想让用户改变这个Deferred对象的状态。就好像电视节目,很多人都可以定制,但是何时播放什么节目,观众个人是不能改变的。这就是deferred.promise方法的作用。

deferred.promise方法返回的Promise对象,允许其他函数添加回调函数 (done, fail, always, pipe, progress, 和 state) ,但是其他函数不能改变这个对象的状态 (resolve, reject, notify, resolveWith, rejectWith, 和 notifyWith) 。

请看下面的例子:

function GetPromise() {

var deferred = $.Deferred();

deferred.resolve();

return deferred.promise();

}

var promise = GetPromise();

promise.done(function () {

alert("promise.done");

});

promise.always(function () {

alert("promise.always");

});

9. deferred.isRejected 和 deferred.isResolved


deferred.isRejected 和 deferred.isResolved是用来指示Deferred对象是被resolve了还是reject了。

var deferred = $.Deferred();

deferred.then(function () {

$.get(

"content.txt",

function (resp) {

alert(resp);

}

);

}

);

deferred.reject();

alert(deferred.isResolved());

以上的代码,执行结果是弹出false

deferred.isRejected 和 deferred.isResolved在JQuery1.5加入,从JQuery1.7开始,使用deferred.state()代替。

10. deferred.pipe


deferred.resolve,deferred.reject等函数中都可以传递参数,比如下面的例子:

var deferred = $.Deferred();

deferred.done(function (arg) {

alert(arg);

});

deferred.resolve( 5 );

对于这个例子,如果我们想让参数在传递给回调函数之前进行一些转换,该怎么办哪?这就是deferred.pipe的作用。pipe顾名思义是管道的意思,就是让参数(在这里例子中是5)经过一个管道,然后到达回调函数。在这个管道中,可以对这个参数进行任意加工处理。这里需要注意的是,这里的管道是我们另外接出来的一个分支,而不会影响到主管道。

请看下面的例子:

var deferred = $.Deferred();

deferred.done(function (arg) {

alert(arg);

});

var filtered = deferred.pipe(function (arg) {

return arg + "(processed by pipe)"

});

filtered.done(function (arg) {

alert("in filtered:" + arg);

});

deferred.resolve(5);

这个例子会弹出两次,一次弹出5,一次弹出in filtered:5(processed by pipe),展示了主管道和我们自己接出来的管道(filtered)的回调函数的两种不同执行结果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: