daiying.zhang
jQuery延迟对象
Deferred Object
event
so easy…
More then one
:)
document.getElementById('foo').addEventListener('click', function(){
/* something ...*/
});
document.getElementById('foo').addEventListener('click', function(){
/* something else ...*/
});
then..
document.getElementById('foo').addEventListener('click', function(){
/* something ...*/
});
document.getElementById('foo').addEventListener('click', function(){
/* something else ...*/
});
document.getElementById('foo').addEventListener('click', function(){
/* something more ...*/
});
document.getElementById('foo').addEventListener('click', function(){
/* something more then more ...*/
});
document.getElementById('foo').addEventListener('click', function(){
/* oh my god ! */
});
var img = new Image();
img.onload = function(){
    //...
    alert('load');
}
img.src = "http://localhost/aaa.jpg?t=" + Math.random();
// ...
setTimeout(function(){
    alert(img.complete)
    img.onload = function(){
        // todo something
        alert('ok');
    }
}, 3000)
then..
document.getElementById('foo').addEventListener('click', function(){
/* something ...*/
});
document.getElementById('foo').addEventListener('click', function(){
/* something else ...*/
});
document.getElementById('foo').addEventListener('click', function(){
/* something more ...*/
});
document.getElementById('foo').addEventListener('click', function(){
/* something more then more ...*/
});
document.getElementById('foo').addEventListener('click', function(){
/* oh my god ! */
});
async
顺序
?
:(
?
:)
setTimeout(function(){
/* this may takes a long time*/
var value = foo(65535);
/* call it here */
calc(result);
}, 5000)
//calc(result);
then…
step1(1, function(){
step2(2, function(){
setp3(3, function(){
setp4(4, function(){
// Oh my god !
})
})
}
})
“Callback hell”
代码变复杂	 
不利于模块化	 
可维护性差	 
紧耦合
Ajax
$.ajax({
url: 'http://www.xxx.com/api',
type: 'POST',
success: function(json){
/* do something */
},
error: function(msg){
/* get an error */
}
})
Exception
try{
setTimeout(function(){
throw new Error(':(')
}, 0)
}catch(e){
alert('get an error');
}
Promise/A
$
jQuery is coming…
Deferred / Callbacks
Callbacks
1、jQuery 1.7 版本中新增的
2、jQuery.Callbacks() 函数返回的对象
3、对象对管理回调列表提供了强⼤大的⽅方式
4、能够增加、删除、触发、禁⽤用回调函数
5、⽀支持不同的参数来控制回调执⾏行
// todo demo
Deferred
一个可链式调用的工具对象,管理回调,简化异步操作	 
可以注册多个回调,调用回调队列,并且传播任何同
步或异步函数的状态	 
三种状态:pending|resolved|rejected	 
状态改变后无法再次修改	 
拥有一个promise对象
API
var def = jQuery.Deferred();
def.done(function(){ console.warn('done'); });
def.fail(function(){ console.warn('fail'); });
console.warn('def.state() ==>', def.state());
def.reject();
console.warn('def.state() ==>', def.state());
var def = jQuery.Deferred();
def.then(function(){ console.warn('done'); },
function(){ console.warn('fail'); });
console.warn('def.state() ==>', def.state());
def.reject();
console.warn('def.state() ==>', def.state());
deferred.then()
deferred.then(fnDone[,	 fnFail[,	 fnPro]])
分别调用deferred的	 
.done(),	 .fail(),	 .progress()	 
添加相应回调函数
return	 this
start
end
version : 1.5.x/1.6.x/1.7.x
创建新Deferred对象	 
(newDefer)
分别调用deferred的	 
.done(),	 .fail(),	 .progress()	 
添加相应回调函数
return	 newDefer.promise()
start
end
version : 1.8.x+
职责:
1、执⾏行回掉函数
2、改变新的Deferred对象的状态
3、返回新的Deferred对象
deferred.then/pipe
分别调用deferred的	 
.done(),	 .fail(),	 .progress()	 
添加相应回调函数
return	 this
start
end
version : 1.5.x/1.6.x/1.7.x
then
创建新Deferred
对象	 
(newDefer)
分别调用deferred的	 
.done(),	 .fail(),	 .progress()	 
添加相应回调函数
return	 
newDefer.promise()
start
end
version : 1.6.x/1.7.x
pipe
创建新Deferred
对象	 
(newDefer)
分别调用deferred的	 
.done(),	 .fail(),	 .progress()	 
添加相应回调函数
return	 
newDefer.promise()
start
end
version : 1.8.x+
then
d1
done function
fail function
state “pending”
… …
doneList Array
failList Array
doneList
0 changeState
1 failList.disable
2 progress.lock
donList和failList实际上不是d1的属性,只是一个局部变量,	 
为了演示方便,加入到d1
d1
done function
fail function
state “pending”
… …
doneList Array
failList Array
doneList
0 changeState
1 failList.disable
2 progress.lock
3 function	 
doneList
0 changeState
1 doneList.disable
2 progress.lock
d2
done function
fail function
then function
… …
doneList Array
failList Array
f1
f2
f3
failList
0 changeState
1 failList.disable
2 progress.lock
d1
done function
then function
state “pending”
… …
doneList Array
failList Array
doneList
0 changeState
1 failList.disable
2 progress.lock
3 function	 
doneList
0 changeState
1 doneList.disable
2 progress.lock
d2
done function
fail function
then function
… …
doneList Array
failList Array
f1
f2
f3
failList
0 changeState
1 failList.disable
2 progress.lock
start
call	 fn	 &	 get	 result	 
(returned)
isPromise
(returned)	 
end
returned.promise()	 
.then(…)
newDefer[resolve
With|rejectWith|
progressWith]
Y
N
d1
done function
fail function
then function
… …
doneList Array
failList Array
doneList
0 changeState
1 failList.disable
2 progress.lock
3 function	 
doneList
0 changeState
1 doneList.disable
2 progress.lock
3 function	 
d2
done function
fail function
then function
… …
doneList Array
failList Array
f1
f2
f3
failList
0 changeState
1 failList.disable
2 progress.lock
3 function
d1
done function
then function
state “resolved”
… …
doneList Array
failList Array
doneList
0 changeState
1 failList.disable
2 progress.lock
3 function	 
doneList
0 changeState
1 doneList.disable
2 progress.lock
3 function	 
d2
done function
fail function
then function
… …
doneList Array
failList Array
f1
f2
f3
failList
0 changeState
1 failList.disable
2 progress.lock
3 function	 
isPromise(returned	 =	 d)	 ==	 true
d.then(d2.resolve,	 d2.reject)
d2.reject()
// TODO ….
:)
d1
done function
fail function
then function
… …
doneList Array
failList Array
failList
0 changeState
1 doneList.disable
2 progress.lock
3 undefined
doneList
0 changeState
1 doneList.disable
2 progress.lock
3 function	 
d2
done function
fail function
then function
… …
doneList Array
failList Array
f1
f2
f3
faiList
0 changeState
1 failList.disable
2 progress.lock
3 function	 
returned	 =	 fnFail	 &&	 returned
returned	 ==	 false
d2.rejectWith()
                var deferred = $.Deferred();
                deferred.then(function(res){
                    console.warn('ok 1');
                },function(err){
                    console.warn('err 1');
                })
                .then(function(res){
                    console.warn('ok 2');
                },function(err){
                    console.warn('err 2');
                })
                .then(function(res){
                    console.warn('ok 3');
                },function(err){
                    console.warn('err 3');
                });         
deferred.reject();
p(deferred)
deferred.done/fail/
progress()
done() or then() ?
顺序 / 值
// then
var def = $.Deferred();
def.then(
    function(val){ console.warn('done +1 ==>', val); return val + 1 }
).then(
    function(val){ console.warn('done +2 ==>', val); return val + 2 }
).then(
    function(val){ console.warn('done +3 ==>', val); return val + 3 }
)
def.resolve(1)
// done
var def = $.Deferred();
def.done(
    function(val){ console.warn('done +1 ==>', val); return val + 1 }
).done(
    function(val){ console.warn('done +2 ==>', val); return val + 2 }
).done(
    function(val){ console.warn('done +3 ==>', val); return val + 3 }
)
def.resolve(1)
// then async
var def = $.Deferred();
def.then( // d1
deferred.promise()
返回一个Deferred的只读对象
var def = $.Deferred();
p(def)
Deferred or Promise ?
Read Only
jQuery.when()
提供一种方法来执行一个或多个对象的回调函数,	 
Deferred(延迟)对象通常表示异步事件。
use
// no-deferred object
var obj = {
  a:1,
  b:2
}
function func1(obj){
  console.warn(obj)
}
function func2(obj){
  console.warn(obj)
}
func1(obj);
func2(obj);
// deferred object
// deferred object
var def1 = $.Deferred();
var def2 = $.Deferred();
function func1(obj){
  console.warn(obj)
}
function func2(obj){
  console.warn(obj)
}
Thx
:)

Deferred

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
    :) document.getElementById('foo').addEventListener('click', function(){ /* something...*/ }); document.getElementById('foo').addEventListener('click', function(){ /* something else ...*/ });
  • 6.
    then.. document.getElementById('foo').addEventListener('click', function(){ /* something...*/ }); document.getElementById('foo').addEventListener('click', function(){ /* something else ...*/ }); document.getElementById('foo').addEventListener('click', function(){ /* something more ...*/ }); document.getElementById('foo').addEventListener('click', function(){ /* something more then more ...*/ }); document.getElementById('foo').addEventListener('click', function(){ /* oh my god ! */ });
  • 7.
    var img =new Image(); img.onload = function(){     //...     alert('load'); } img.src = "http://localhost/aaa.jpg?t=" + Math.random(); // ... setTimeout(function(){     alert(img.complete)     img.onload = function(){         // todo something         alert('ok');     } }, 3000)
  • 8.
    then.. document.getElementById('foo').addEventListener('click', function(){ /* something...*/ }); document.getElementById('foo').addEventListener('click', function(){ /* something else ...*/ }); document.getElementById('foo').addEventListener('click', function(){ /* something more ...*/ }); document.getElementById('foo').addEventListener('click', function(){ /* something more then more ...*/ }); document.getElementById('foo').addEventListener('click', function(){ /* oh my god ! */ });
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
    :) setTimeout(function(){ /* this maytakes a long time*/ var value = foo(65535); /* call it here */ calc(result); }, 5000) //calc(result);
  • 14.
    then… step1(1, function(){ step2(2, function(){ setp3(3,function(){ setp4(4, function(){ // Oh my god ! }) }) } })
  • 15.
  • 16.
  • 17.
  • 18.
    $.ajax({ url: 'http://www.xxx.com/api', type: 'POST', success:function(json){ /* do something */ }, error: function(msg){ /* get an error */ } })
  • 19.
  • 20.
    try{ setTimeout(function(){ throw new Error(':(') },0) }catch(e){ alert('get an error'); }
  • 21.
  • 23.
  • 24.
  • 25.
  • 26.
    1、jQuery 1.7 版本中新增的 2、jQuery.Callbacks()函数返回的对象 3、对象对管理回调列表提供了强⼤大的⽅方式 4、能够增加、删除、触发、禁⽤用回调函数 5、⽀支持不同的参数来控制回调执⾏行
  • 30.
  • 31.
  • 32.
  • 33.
  • 35.
    var def =jQuery.Deferred(); def.done(function(){ console.warn('done'); }); def.fail(function(){ console.warn('fail'); }); console.warn('def.state() ==>', def.state()); def.reject(); console.warn('def.state() ==>', def.state()); var def = jQuery.Deferred(); def.then(function(){ console.warn('done'); }, function(){ console.warn('fail'); }); console.warn('def.state() ==>', def.state()); def.reject(); console.warn('def.state() ==>', def.state());
  • 36.
  • 37.
    deferred.then(fnDone[, fnFail[, fnPro]]) 分别调用deferred的 .done(), .fail(), .progress() 添加相应回调函数 return this start end version : 1.5.x/1.6.x/1.7.x 创建新Deferred对象 (newDefer) 分别调用deferred的 .done(), .fail(), .progress() 添加相应回调函数 return newDefer.promise() start end version : 1.8.x+ 职责: 1、执⾏行回掉函数 2、改变新的Deferred对象的状态 3、返回新的Deferred对象
  • 38.
    deferred.then/pipe 分别调用deferred的 .done(), .fail(), .progress() 添加相应回调函数 return this start end version : 1.5.x/1.6.x/1.7.x then 创建新Deferred 对象 (newDefer) 分别调用deferred的 .done(), .fail(), .progress() 添加相应回调函数 return newDefer.promise() start end version : 1.6.x/1.7.x pipe 创建新Deferred 对象 (newDefer) 分别调用deferred的 .done(), .fail(), .progress() 添加相应回调函数 return newDefer.promise() start end version : 1.8.x+ then
  • 40.
    d1 done function fail function state“pending” … … doneList Array failList Array doneList 0 changeState 1 failList.disable 2 progress.lock donList和failList实际上不是d1的属性,只是一个局部变量, 为了演示方便,加入到d1
  • 41.
    d1 done function fail function state“pending” … … doneList Array failList Array doneList 0 changeState 1 failList.disable 2 progress.lock 3 function doneList 0 changeState 1 doneList.disable 2 progress.lock d2 done function fail function then function … … doneList Array failList Array f1 f2 f3 failList 0 changeState 1 failList.disable 2 progress.lock
  • 42.
    d1 done function then function state“pending” … … doneList Array failList Array doneList 0 changeState 1 failList.disable 2 progress.lock 3 function doneList 0 changeState 1 doneList.disable 2 progress.lock d2 done function fail function then function … … doneList Array failList Array f1 f2 f3 failList 0 changeState 1 failList.disable 2 progress.lock start call fn & get result (returned) isPromise (returned) end returned.promise() .then(…) newDefer[resolve With|rejectWith| progressWith] Y N
  • 43.
    d1 done function fail function thenfunction … … doneList Array failList Array doneList 0 changeState 1 failList.disable 2 progress.lock 3 function doneList 0 changeState 1 doneList.disable 2 progress.lock 3 function d2 done function fail function then function … … doneList Array failList Array f1 f2 f3 failList 0 changeState 1 failList.disable 2 progress.lock 3 function
  • 44.
    d1 done function then function state“resolved” … … doneList Array failList Array doneList 0 changeState 1 failList.disable 2 progress.lock 3 function doneList 0 changeState 1 doneList.disable 2 progress.lock 3 function d2 done function fail function then function … … doneList Array failList Array f1 f2 f3 failList 0 changeState 1 failList.disable 2 progress.lock 3 function isPromise(returned = d) == true d.then(d2.resolve, d2.reject) d2.reject() // TODO …. :)
  • 45.
    d1 done function fail function thenfunction … … doneList Array failList Array failList 0 changeState 1 doneList.disable 2 progress.lock 3 undefined doneList 0 changeState 1 doneList.disable 2 progress.lock 3 function d2 done function fail function then function … … doneList Array failList Array f1 f2 f3 faiList 0 changeState 1 failList.disable 2 progress.lock 3 function returned = fnFail && returned returned == false d2.rejectWith()                 var deferred = $.Deferred();                 deferred.then(function(res){                     console.warn('ok 1');                 },function(err){                     console.warn('err 1');                 })                 .then(function(res){                     console.warn('ok 2');                 },function(err){                     console.warn('err 2');                 })                 .then(function(res){                     console.warn('ok 3');                 },function(err){                     console.warn('err 3');                 });          deferred.reject(); p(deferred)
  • 46.
  • 48.
  • 49.
    顺序 / 值 //then var def = $.Deferred(); def.then(     function(val){ console.warn('done +1 ==>', val); return val + 1 } ).then(     function(val){ console.warn('done +2 ==>', val); return val + 2 } ).then(     function(val){ console.warn('done +3 ==>', val); return val + 3 } ) def.resolve(1) // done var def = $.Deferred(); def.done(     function(val){ console.warn('done +1 ==>', val); return val + 1 } ).done(     function(val){ console.warn('done +2 ==>', val); return val + 2 } ).done(     function(val){ console.warn('done +3 ==>', val); return val + 3 } ) def.resolve(1) // then async var def = $.Deferred(); def.then( // d1
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 57.
    use // no-deferred object varobj = {   a:1,   b:2 } function func1(obj){   console.warn(obj) } function func2(obj){   console.warn(obj) } func1(obj); func2(obj); // deferred object // deferred object var def1 = $.Deferred(); var def2 = $.Deferred(); function func1(obj){   console.warn(obj) } function func2(obj){   console.warn(obj) }
  • 58.