jQueryのdeferredオブジェクトの詳細(二)
27119 ワード
Deferredオブジェクトは$.Deferred構造、$.Deferredは簡単な工場モードとして実現された.
$.Deferredの実装は3つの$を作成する.Callbacksオブジェクトは、それぞれ成功done、失敗fail、処理中processの3つの状態 を表す.は3つの処理結果に対応し、resolve、reject、notify は、state、always、then、primiseメソッド を有するpromiseオブジェクトを作成する. primiseオブジェクトを拡張することによって最終的なDeferredオブジェクトを生成し、他のコードを阻止してこのdeferredオブジェクトの状態を変更する、deferred.promise()はdeferredオブジェクトの状態を変えることができず、作用も現在の状態が変わらないことを保証するものではない Deferredの3ドルについてお話ししましたCallback()のインスタンスで、Deferred自体はこの3つのオブジェクトを中心により高度な抽象化を行います.以下はDeferredオブジェクトのコアメソッドです
1.done/fail/progressはcallbacksです.add、コールバック関数をコールバックマネージャに追加
2.resolve/reject/notifyはcallbackです.Fire、コールバック関数(またはキュー)の実行
$.Deferredメンバーのメソッド
1.$.Deferred()
非同期キューインスタンスオブジェクトdeferredを生成
functionパラメータを受け入れます.functionではthisを使用して現在の非同期キューインスタンスを呼び出すことができます.
2.deferred.done(fn)
成功時にトリガーされるコールバックfn
3.deferred.fail(fn)
失敗時にトリガーされるコールバック
4.deferred.progress(fn)
処理中にトリガーされたコールバック
5.deferred.resolve/resolveWith([context],args)
ここは$に等しい.Callbacks().(fire/fireWith)
タスク処理に成功した後、このメソッドを使用して成功イベントをトリガーし、doneキューに追加されたコールバックがトリガーされます.
6.deferred.reject/rejectWith([context],args)
ここは$に等しい.Callbacks().(fire/fireWith)
タスク処理に成功した後、このメソッドを使用して成功イベントをトリガーします.failキューに参加したコールバックがトリガーされます.
7.deferred.notify/notifyWith([context],args)
ここは$に等しい.Callbacks().(fire/fireWith)
タスク処理では、このメソッドを使用して処理中のイベントをトリガーできます.
8.deferred.promise()
deferred.promise()は、deferredオブジェクトの状態を変更するために他のコードをブロックするだけです.promise()メソッドが返すdeferredオブジェクトは,resolve,reject,progress,resolveWith,rejectWith,progressWithといった状態を変える方法がない.
9.deferred.then([fnDone,fnFail,fnProgress])
done|fail|progressの3つの状態のコールバックに対応する3つのコールバック関数を直接入力ことができる.when($.ajax("/main.php")).then(successFunc,failureFunc,proFunc)、1番目のパラメータはdone()メソッドのコールバック関数、2番目のパラメータはfailメソッドのコールバック関数、3番目のパラメータはprogressのコールバック関数、または1つのパラメータのみを伝えることができ、done()メソッドのコールバック関数
10.deferred.always(fn)
最後にresolveでもrejectでもfnがトリガーされます
11.$.when(mission1,[mission2,mission3,...])
この件をjQueryに載せる方法は、複数の操作にコールバック関数、例$を指定する.when($.ajax("test1.html",$.ajax("test2.html"))).done(fn).fail(fn)
$.Deferredソース構造
$.Deferredの実装
1.done/fail/progressはcallbacksです.add、コールバック関数をコールバックマネージャに追加
2.resolve/reject/notifyはcallbackです.Fire、コールバック関数(またはキュー)の実行
$.Deferredメンバーのメソッド
1.$.Deferred()
非同期キューインスタンスオブジェクトdeferredを生成
functionパラメータを受け入れます.functionではthisを使用して現在の非同期キューインスタンスを呼び出すことができます.
2.deferred.done(fn)
成功時にトリガーされるコールバックfn
3.deferred.fail(fn)
失敗時にトリガーされるコールバック
4.deferred.progress(fn)
処理中にトリガーされたコールバック
5.deferred.resolve/resolveWith([context],args)
ここは$に等しい.Callbacks().(fire/fireWith)
タスク処理に成功した後、このメソッドを使用して成功イベントをトリガーし、doneキューに追加されたコールバックがトリガーされます.
6.deferred.reject/rejectWith([context],args)
ここは$に等しい.Callbacks().(fire/fireWith)
タスク処理に成功した後、このメソッドを使用して成功イベントをトリガーします.failキューに参加したコールバックがトリガーされます.
7.deferred.notify/notifyWith([context],args)
ここは$に等しい.Callbacks().(fire/fireWith)
タスク処理では、このメソッドを使用して処理中のイベントをトリガーできます.
8.deferred.promise()
deferred.promise()は、deferredオブジェクトの状態を変更するために他のコードをブロックするだけです.promise()メソッドが返すdeferredオブジェクトは,resolve,reject,progress,resolveWith,rejectWith,progressWithといった状態を変える方法がない.
9.deferred.then([fnDone,fnFail,fnProgress])
done|fail|progressの3つの状態のコールバックに対応する3つのコールバック関数を直接入力ことができる.when($.ajax("/main.php")).then(successFunc,failureFunc,proFunc)、1番目のパラメータはdone()メソッドのコールバック関数、2番目のパラメータはfailメソッドのコールバック関数、3番目のパラメータはprogressのコールバック関数、または1つのパラメータのみを伝えることができ、done()メソッドのコールバック関数
10.deferred.always(fn)
最後にresolveでもrejectでもfnがトリガーされます
11.$.when(mission1,[mission2,mission3,...])
この件をjQueryに載せる方法は、複数の操作にコールバック関数、例$を指定する.when($.ajax("test1.html",$.ajax("test2.html"))).done(fn).fail(fn)
$.Deferredソース構造
/**
Deferred ,
*/
jQuery.extend({
/**
Deferred ," " 。 Deferred, ,
: , deferred, deferred , func.call(deferred,deferred) deferred func
: ( ), , (API)。
* @param {Function} func ( call , deferred )
* @return {Object} deferred
*/
Deferred: function (func) {
/**
*
* (deferred) :
*
Deferred
( ( ))
( ( ))
(jQuery.Callbacks )
( )
* , callbacklist doneList, failList, processList
* resolve , “ ” (deferred “ ” “ ”, done( ))
* reject , “ ” ,deferred , “ ” “ ”, fail( )
* notify , “ , ”
* done ( )
* fail ( )
* progress
* resolved
* rejected
*/
var tuples = [
// action , add listener ( ),listener list ( ),final state
["resolve", "done", jQuery.Callbacks("once memory"), "resolved"],
["reject", "fail", jQuery.Callbacks("once memory"), "rejected"],
["notify", "progress", jQuery.Callbacks("memory")]
],
// ,(deferred ) :pending( ) resolved( ) rejected( )
state = "pending",
/**
* promise , ,
* :1. deferred ,promise extend deferred ,
* 2. deferred , deferred , , deferred , done,fail,progress
*/
promise = {
/**
* return {String} ( )
*/
state: function () {
return state;
},
/**
resolve reject, fn
doneList failList list ( ), deferred ,
* return {Object}
*/
always: function () {
deferred.done(arguments).fail(arguments);
return this;
},
/**
, 3 , , deferred
* @param {Function} fnDone ,done()
* @param {Function} fnFail ,fail()
* @param {Function} fnProgress ,progress()
* @return {Object}
*/
then: function ( /* fnDone, fnFail, fnProgress */) {
// , funs
var fns = arguments;
// newDefer
return jQuery.Deferred(function (newDefer) {
jQuery.each(tuples, function (i, tuple) {
// i tuples
// tuple tuples[i]
var action = tuple[0],// tuple[0] resolve,reject,notify
fn = jQuery.isFunction(fns[i]) && fns[i];//
/**
* deferred
* tuple[1] [done | fail | progress]
* fn
* deferred callbacklist( ) , fn , :
* 1. fn ,( :undefined null), newDefer ([resolve | reject | notify] ), newDefer ( )deferred (done,fail,progress)
* 2. fn , (ret) deferred , :
* a) deferred , newDefer ([resolve | reject | notify] ) ret , newDefer ret
* b) deferred , ret newDefer , this deferred, newDefer , this , ,Ps: newDefer ( ) deferred ( )。
*/
// deferred.done,deferred.fail,deferred.progess ;
deferred[tuple[1]](function () {
// ( )
var returned = fn && fn.apply(this, arguments);
if (returned && jQuery.isFunction(returned.promise)) {
returned.promise()
.done(newDefer.resolve)
.fail(newDefer.reject)
.progress(newDefer.notify);
} else {
newDefer[action + "With"](this === promise ? newDefer.promise() : this, fn ? [returned] : arguments);
}
});
});
// ,
fns = null;
}).promise();//
},
/**
( deferred promise )
* @param {Object}
* @return {Object} , promise , promise
*/
promise: function (obj) {
return obj != null ? jQuery.extend(obj, promise) : promise;
}
},
//
deferred = {};
// pipe then , pipe filter
promise.pipe = promise.then;
jQuery.each(tuples, function (i, tuple) {
// , list,3 $.Callback()
var list = tuple[2],
stateString = tuple[3]; // resolved,rejected
// ( )
// promise[done|fail|progress]=list.add;
// add , list [done|fail|progress],
promise[tuple[1]] = list.add;
/*
* add
* fire fireWidth
* fireWidth
*/
// stateString ,progress , [done|fail]
// :1. ;2. ;3. ( )
if (stateString) {
list.add(function () {
// state = [ resolved | rejected ]
//
state = stateString;
//
// 0^1 = 1 1^1 = 0
// ,
// ,
// [ reject_list | resolve_list ].disable; progress_list.lock
}, tuples[i ^ 1][2].disable, tuples[2][2].lock);
}
// ( )
// deferred[ resolve | reject | notify ]
deferred[tuple[0]] = function () {
deferred[tuple[0] + "With"](this === deferred ? promise : this, arguments);
return this;
};
deferred[tuple[0] + "With"] = list.fireWith;
});
// ( promise extend deferred )
promise.promise(deferred);
// func , , this
if (func) {
func.call(deferred, deferred);
}
//
return deferred;
},
// $.when
// , 。
// Deferred ,
// function ,
when: function (subordinate /* , ..., subordinateN */) {
var i = 0,
//arguments
resolveValues = core_slice.call(arguments),
length = resolveValues.length,
//
//subordinate && jQuery.isFunction(subordinate.promise) subordinate Deferred
remaining = length !== 1 || (subordinate && jQuery.isFunction(subordinate.promise)) ? length : 0,
//
deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
// |
// :
// , 。
updateFunc = function (i, contexts, values) {
return function (value) {
contexts[i] = this;
values[i] = arguments.length > 1 ? core_slice.call(arguments) : value;
// ,
if (values === progressValues) {
deferred.notifyWith(contexts, values);
} else if (!(--remaining)) {
// , 0
// ,
//
deferred.resolveWith(contexts, values);
}
};
},
progressValues, progressContexts, resolveContexts;
// ,
// 1
if (length > 1) {
progressValues = new Array(length);
progressContexts = new Array(length);
// ,
resolveContexts = new Array(length);
for (; i < length; i++) {
if (resolveValues[i] && jQuery.isFunction(resolveValues[i].promise)) {
//
resolveValues[i].promise()
//
.done(updateFunc(i, resolveContexts, resolveValues))
// , 。
.fail(deferred.reject)
//
.progress(updateFunc(i, progressContexts, progressValues));
} else {
// , remain
--remaining;
}
}
}
//
if (!remaining) {
deferred.resolveWith(resolveContexts, resolveValues);
}
return deferred.promise();
}
});