本文作者:IMWeb json 原文出处:IMWeb社区 未经同意,禁止转载
我们知道JavaScript是单线程,如果遇到某些耗时很长的javascript操作,那么其他的操作就必须等待。,通常的解决方法是将那些排在后面的操作,写成“回调函数”(callback)的形式。事先规定当他们结束运行后,应该调用那些函数。但是这样有一些显著缺点:
deferred对象是jQuery的回调函数解决方案,它解决了如何处理耗时操作的问题,对那些操作提供了更好的控制,以及统一的编程接口。 下面来看下他的具体的使用方法:
先看下传统写法:
$.ajax({
url: "test.html",
success: function(){
console.log(“成功”);
},
error:function(){
console.log(“失败”);
}
});
其中success 和 error方法分别指定操作成功和失败的回调函数。
现在新的ajax操作的写法是这样的:
$.ajax("test.html")
.done(function(){console.log(“成功”); })
.fail(function(){console.log(“失败”); });
done()相当于success方法,fail()相当于error方法。
注意,如果使用的是低于1.5.0版本的jQuery,返回的是XHR对象,没法进行链式操作;如果高于1.5.0版本,返回的是deferred对象,可以进行链式操作。
新的ajax操作也可以这样写:
$.ajax("test.html").then(function(){
console.log(“成功”);
}, function(){
console.log(“失败”); }
);
这里介绍下deferred.then() 方法,有时为了省事,可以把done()和fail()合在一起写,这就是then()方法。如果then()有两个参数,那么第一个参数是done()方法的回调函数,第二个参数是fail()方法的回调方法。如果then()只有一个参数,那么等同于done()。
$.deferred()方法,作用是生成一个deferred对象,它允许你自由添加多个回调函数。
var def = $.Deferred();
def.done(function(){
console.log(“成功”);
}).fail(function(){
console.log(“失败”);
}).done(function(){
console.log(“再一次成功”);
})
回调函数可以添加任意多个,它们按照添加顺序执行。 其中,done() 和 fail()这两个方法都用来绑定回调函数。done()指定操作成功后的回调函数,fail()指定失败后的回调函数。
state方法用来返回deferred对象目前的状态,deferred对象有三种状态:操作还没有完成、操作成功、操作失败,对应state方法的返回值为:pending、resolved、rejected
var deferred = $.Deferred();
alert(deferred.state()); // "pending"
deferred.resolve();
alert(deferred.state()); // "resolved"
前面说过deferred对象有三种执行状态----未完成,已完成和已失败。如果执行状态是"已完成"(resolved),deferred对象立刻调用done()方法指定的回调函数;如果执行状态是"已失败",调用fail()方法指定的回调函数;如果执行状态是"未完成",则继续等待,或者调用progress()方法指定的回调函数
var def = $.Deferred();
def.done(function(value) {
alert(value);
}).fail(function(){
alert("hello");
})
def.resolve("hello world");
$.when()接受多个deferred对象作为参数,当它们全部运行成功后,才调用resolved状态的回调函数,但只要其中有一个失败,就调用rejected状态的回调函数。它允许你为多个事件指定一个回调函数
$.when($.ajax("test1.html"), $.ajax("test2.html"))
.done(function(){ alert("成功"); })
.fail(function(){ alert("失败"); });
上面的代码先执行两个操作$.ajax("test1.html")和$.ajax("test2.html"),如果都成功了,就运行done()指定的回调函数;如果有一个失败或都失败了,就执行fail()指定的回调函数。
注意如果when()它的参数返回的不是一个Deferred或Promise对象,那么when方法的回调函数将立即运行。
普通函数如何使用回调函数呢? 例如有这样的函数
var wait = function(){
setTimeout(function(){
alert("执行完毕!");
},3000);
};
wait();
现在为他指定回调函数
var dtd = $.Deferred(); // 新建一个deferred对象
var wait = function(dtd){
setTimeout( function(){
alert("执行完毕!");
dtd.resolve(); // 改变deferred对象的执行状态
},3000);
return dtd;
};
$.when(wait(dtd))
.done(function(){ alert("哈哈,成功了!"); })
.fail(function(){ alert("出错啦!"); });
这样wait函数的返回值就是Deferred对象,when()函数能生效,wait()函数运行完,就会自动运行done()方法指定的回调函数。
这个方法也是用来指定回调函数的,它的作用是,不管调用的是deferred.resolve()还是deferred.reject(),最后总是执行。
$.ajax( "test.html" )
.always( function() { alert("已执行!");} );