X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=0.6.x%2Fjs%2F06_net%2F00_XNet.js;h=90693963a7b992dd65e4e0d73dccea361c80d8ee;hb=4e4ab3be10850546063d4a4b93250ed142bb8cd2;hp=02578225f287c25bd38941cf095f1016e2dbd8ff;hpb=6c4c72f7e862c9f950bfb3562adda24c39498abd;p=pettanr%2FclientJs.git diff --git a/0.6.x/js/06_net/00_XNet.js b/0.6.x/js/06_net/00_XNet.js index 0257822..9069396 100644 --- a/0.6.x/js/06_net/00_XNet.js +++ b/0.6.x/js/06_net/00_XNet.js @@ -7,9 +7,62 @@ /** - * 通信のキャンセル 通信中の場合は停止&破棄する kill(), busy() メソッドだけを持つ。X.Pair によって、プライベートメンバは隠蔽される。X_EVENT_PROGRESS, X_EVENT_SUCCESS, X_EVENT_ERROR, X_EVENT_TIMEOUT, X_EVENT_CANCELED - * 通信待ち中はキャンセル&破棄、通信中の場合は通信の中断&破棄を行う。 - * SUCCESS, ERROR, TIMEOUT イベント以降は kill() は無視される。X.Net インスタンスは COMPLETE で自動で破棄される。 + *

state() メソッドだけを持つ。通信用のプロパティは X.Pair によって隠蔽されています。 + *

通信のキャンセル

+ *

kill() で通信待ち中はキャンセル&破棄、通信中の場合は通信の中断&破棄を行う。 + *

イベント

+ *
+ *
X.Event.PROGRESS
通信進行状況 + *
X.Event.SUCCESS
通信成功 + *
X.Event.ERROR
通信エラー タイムアウトの場合、e.timeout == true で分かる。 + *
X.Event.CANCELED
通信のユーザー、プログラムによるキャンセル。SUCCESS, ERROR, COMPLETE 後に kill()してもCANCELEDは呼ばれません。 + *
X.Event.COMPLETE
通信完了。SUCCESS, ERROR, CANCELED 後に発生。 + *
+ *

X.Net インスタンスは COMPLETE 後に自動で破棄される。 + *

必須プロパティ

+ *
+ *
url
URL + *
type
'xhr', 'jsonp', 'form', 'image', 'img' + *
xhr
URL { url : 'hoge', type : 'xhr' } の省略形 + *
jsonp
URL { url : 'hoge', type : 'jsonp' } の省略形 + *
form
URL { url : 'hoge', type : 'form' } の省略形 + *
image, img
URL { url : 'hoge', type : 'image' } の省略形 + *
+ *

XHR 用プロパティ

+ *
+ *
method
'GET', 'POST' 未指定かつ postdata を設定している場合、'POST' になる。 + *
params
url パラメータを object で渡すことが出来る。 + *
postdata
string, object の場合は X.String.serialize される。 + *
async
boolean + *
username
BASIC 認証 + *
password
BASIC 認証 + *
headers
object xhr.setRequestHeader する値 + *
timeout
タイムアウト ms + *
cache
headers[ 'Pragma' ] = 'no-cache' 等を設定するか? + *
dataType
'text', 'json', 'xml', 'blob', 'arraybuffer' 等。xhr.responseType に指定する値 + *
mimeType
'text/xml', 'audio/mpeg' 等。xhr.overrideMimeType する値 + *
auth
X.OAuth2 インスタンス(OAuth2 サービスの定義) + *
getFullHeaders
getAllResponseHeaders() をパースしたハッシュを返す。値は配列になっている。XDR は Content-Type しか取得でいない。 + *
canUse
未実装。gadget proxy, YQL, YPipes 等のマッシュアップの許可。現在は test : 'gadget' としている + *
+ * + *

JSONP 用プロパティ

+ *
+ *
params
url パラメータを object で渡すことが出来る。 + *
callbackName
callback(json) コールバック名が固定されている際に指定。または &callback=hoge 以外の名前でコールバックを指定する場合に params と callbackName に書いておく。url パラメータに callback が無く、callbackName もない場合、フレームワーク内で自動で設定される + *
charset
ページと異なるjsonpを読み込む場合に指定 'EUC-JP', 'Shift-JIS' 等 script タグの charset に入る。https://code.google.com/p/ajaxzip3/issues/detail?id=5 + *
useFireWall
異なるドメインに jsonp を読み込んだ後、xdomain iframe 通信を使ってデータを受け取る。不正なコードの実行を防ぐことが出来る(はず)、未実装 + *
+ * + *

Form 用プロパティ

+ *
+ *
method
'GET' or 'POST' + *
params
パラメータ object は input タグの name & value に展開される。object を入れ子にすることはできない。 + *
target
'_self', '_parent', '_top' の場合、ページから離脱する。target を指定せず同一ドメインの場合 response に body.innerHTML が返る。TODO X.Window + *
timeout
ms タイムアウト時間、省略可能 + *
charset
未実装 + *
+ * * @alias X.Net * @class 各種ネットワーク機能をラップしインターフェイスを共通化する。 * @constructs Net @@ -19,11 +72,17 @@ * .listen( X.Event.PROGRESS ) * .listenOnce( [ X.Event.SUCCESS, X.Event.ERROR, X.Event.TIMEOUT, X.Event.CANCELED ] ); * + * // XHR - GET + * var net = X.Net( urlString ); + * * // XHR - POST * var net = X.Net( { xhr : urlString, postdata : myData } ); * * // JSONP - * var net = X.Net( { jsonp : urlString, staticCallbackName : callbackName, useXDomainWall : false } ); + * var net = X.Net( { jsonp : urlString, params : params, callbackName : callbackName, charset : charset, useFireWall : false } ); + * + * // Form + * var net = X.Net( { form : urlString, method : 'POST', target : '_self', params : {} } ); * * // Image preload & getSize * var net = X.Net( { image : src, sizeDetection : true } ); @@ -34,54 +93,45 @@ X[ 'Net' ] = X_EventDispatcher[ 'inherits' ]( 'X.Net', X_Class.NONE, { + 'Constructor' : function( urlOrObject, opt_options ){ - var v, opt, url, type; + var opt, url, type, auth; if( X_Type_isObject( opt = urlOrObject ) ){ - if( v = opt[ 'xhr' ] ){ - url = v; + //{+xhr + if( X_Type_isString( url = opt[ 'xhr' ] ) ){ type = X_NET_TYPE_XHR; } else - if( v = opt[ 'jsonp' ] ){ - url = v; + //}+xhr + //{+jsonp + if( X_Type_isString( url = opt[ 'jsonp' ] ) ){ type = X_NET_TYPE_JSONP; } else - if( v = opt[ 'img' ] || opt[ 'image' ] ){ - url = v; + //}+jsonp + //{+netimage + if( X_Type_isString( url = opt[ 'img' ] || opt[ 'image' ] ) ){ type = X_NET_TYPE_IMAGE; } else - if( v = opt[ 'form' ] ){ - url = v; + //}+netimage + //{+netform + if( X_Type_isString( url = opt[ 'form' ] ) ){ type = X_NET_TYPE_FORM; } else - if( v = opt[ 'type' ] ){ - - switch( v ){ - case 'xhr' : - type = X_NET_TYPE_XHR; - break; - case 'jsonp' : - type = X_NET_TYPE_JSONP; - break; - case 'img' : - case 'image' : - type = X_NET_TYPE_IMAGE; - break; - case 'from' : - type = X_NET_TYPE_FORM; - break; - default : - alert( 'X.Net args error' ); - return; - }; - + //}+netform + if( !( type = X_NET_NAME_TO_ID[ opt[ 'type' ] ] ) ){ + //{+dev + alert( 'X.Net args error' ); + //}+dev + return; + } else { + url = opt[ 'url' ]; }; - + //{+dev if( !X_Type_isString( url ) ){ alert( 'X.Net args error' ); return; }; - + //}+dev } else if( X_Type_isString( urlOrObject ) ){ url = urlOrObject; @@ -92,39 +142,58 @@ X[ 'Net' ] = X_EventDispatcher[ 'inherits' ]( type = X_NET_TYPE_XHR; opt = { 'url' : url, 'method' : 'GET' }; }; - + //{+dev } else { alert( 'X.Net args error' ); return; + //}+dev }; + // auth の退避 + if( auth = opt[ 'auth' ] ){ + delete opt[ 'auth' ]; + }; + opt = X_Object_deepCopy( opt ); + if( auth ){ + opt[ 'auth' ] = auth; // auth は deep copy されるとまずい + }; + + // params を url に追加 但し form は除く + if( opt[ 'params' ] && type !== X_NET_TYPE_FORM ){ + url = X_URL_create( url, opt[ 'params' ] ); + delete opt[ 'params' ]; + }; + if( type === X_NET_TYPE_XHR ){ opt[ 'method' ] = opt[ 'method' ] || ( opt[ 'postdata' ] ? 'POST' : 'GET' ); - + // XDomain 不可 -> Flash, Gears, Silverlight, canUseGadget なら gadget に切替? // PUT DELETE UPDATE 不可 -> Flash, Gears, Silverlight, canUseGadget なら gadget に切替? + // xプロトコル(X_URL_isSameProtocol) な binary のロード -> gadget 内で proxyURL による XHR // or X_EVENT_ERROR - }; + opt[ 'dataType' ] = opt[ 'dataType' ] || X_URL_getEXT( url ); + }; - opt = X_Object_clone( opt ); opt.netType = type; opt[ 'url' ] = url; X_Pair_create( this, opt ); - this[ 'listen' ]( [ X_EVENT_BEFORE_KILL_INSTANCE, X_EVENT_KILL_INSTANCE ], X_NET_proxyDispatch ); + this[ 'listen' ]( X_EVENT_KILL_INSTANCE, X_NET_proxyDispatch ); X_NET_QUEUE_LIST[ X_NET_QUEUE_LIST.length ] = this; !X_NET_currentQueue && X_NET_shiftQueue(); }, - + /** - * 現在通信中か?調べる。false の場合、通信の順番待ちか、通信が終了している。 - * @alias Net.prototype.busy + * 現在の状態。1:順番待ち, 2:通信中, 3:通信完了フェーズ + * @alias Net.prototype.state */ - 'busy' : function(){ - return this === X_NET_currentQueue && X_NET_currentWrapper._busy; + 'state' : function(){ + return this === X_NET_currentQueue ? + ( X_NET_completePhase ? 3 : 2 ) : + 0 <= X_NET_QUEUE_LIST.indexOf( this ) ? 1 : 0; } } ); @@ -142,13 +211,21 @@ var X_NET_TYPE_XHR = 1, X_NET_TYPE_FORM = 3, X_NET_TYPE_IMAGE = 4, + X_NET_NAME_TO_ID = { + 'xhr' : X_NET_TYPE_XHR, + 'jsonp' : X_NET_TYPE_JSONP, + 'form' : X_NET_TYPE_FORM, + 'img' : X_NET_TYPE_IMAGE, + 'image' : X_NET_TYPE_IMAGE + }, + X_NET_QUEUE_LIST = [], - X_NET_XHRWrapper, - X_NET_JSONPWrapper, - X_NET_FormWrapper, - X_NET_ImageWrapper, - X_NET_GIMRWrapper, + X_XHR, + X_JSONP, + X_FormSender, + X_ImgLoader, + X_GadgetXHR, X_NET_currentWrapper, X_NET_currentQueue, @@ -156,88 +233,141 @@ var X_NET_TYPE_XHR = 1, X_NET_completePhase; function X_NET_proxyDispatch( e ){ - var i, flag; + var i, flag, auth; switch( e.type ){ - case X_EVENT_BEFORE_KILL_INSTANCE : - if( this === X_NET_currentQueue && X_NET_completePhase ) return X_Callback_PREVENT_DEFAULT; - break; - case X_EVENT_KILL_INSTANCE : - i = X_NET_QUEUE_LIST.indexOf( this ); - - if( i !== -1 ){ - X_NET_QUEUE_LIST.splice( i, 1 ); - flag = true; + if( this === X_NET_currentQueue && X_NET_completePhase ){ + if( X_NET_completePhase === 1 ){ + this[ 'unlisten' ]( X_EVENT_COMPLETE, X_NET_proxyDispatch ) + [ 'dispatch' ]( X_EVENT_COMPLETE ); + }; + X_NET_shiftQueue( true ); + X_Pair_release( this ); + X_NET_completePhase = 0; } else if( this === X_NET_currentQueue ){ X_NET_currentWrapper.cancel(); - X_NET_shiftQueue(); + X_NET_shiftQueue( true ); + flag = true; + } else + if( ( i = X_NET_QUEUE_LIST.indexOf( this ) ) !== -1 ){ + X_NET_QUEUE_LIST.splice( i, 1 ); flag = true; }; if( flag ){ // flag が立つ場合、これは中断 this[ 'dispatch' ]( X_EVENT_CANCELED ); this[ 'dispatch' ]( { type : X_EVENT_COMPLETE, 'lastEventType' : X_EVENT_CANCELED } ); - X_Pair_release( this ); + X_Pair_release( this ); }; break; case X_EVENT_PROGRESS : this[ 'dispatch' ]( e ); break; - case X_EVENT_SUCCESS : + case X_EVENT_ERROR : - case X_EVENT_TIMEOUT : - X_NET_completePhase = true; - this - [ 'listenOnce' ]( X_EVENT_COMPLETE, X_NET_proxyDispatch ) - [ 'unlisten' ]( [ X_EVENT_BEFORE_KILL_INSTANCE, X_EVENT_KILL_INSTANCE ], X_NET_proxyDispatch ) - [ 'asyncDispatch' ]( e ); - this[ 'asyncDispatch' ]( 32, { type : X_EVENT_COMPLETE, 'lastEventType' : e.type } ); + if( e.status === 401 ){ + if( auth = X_Pair_get( this )[ 'auth' ] ){ + X_Pair_get( auth ).onAuthError( auth, e ); + // TODO 破棄しないで待機。 + }; + }; + + case X_EVENT_SUCCESS : + X_NET_completePhase = 1; + this[ 'listenOnce' ]( X_EVENT_COMPLETE, X_NET_proxyDispatch ) + [ 'asyncDispatch' ]( 32, { type : X_EVENT_COMPLETE, 'lastEventType' : e.type } ); + + this[ 'asyncDispatch' ]( e ); break; + case X_EVENT_COMPLETE : - X_Pair_release( this ); - X_NET_shiftQueue(); - X_NET_completePhase = false; + X_NET_completePhase = 2; this[ 'kill' ](); break; }; }; -function X_NET_shiftQueue(){ +// TODO _busy は X.Net で触る. +function X_NET_shiftQueue( currentKilled ){ + var q, auth, authSettings; if( X_NET_currentQueue ){ - if( X_NET_currentWrapper._busy ) return; + if( !currentKilled ) return; + X_NET_currentWrapper - [ 'unlisten' ]( [ X_EVENT_PROGRESS, X_EVENT_SUCCESS, X_EVENT_ERROR, X_EVENT_TIMEOUT ], X_NET_currentQueue, X_NET_proxyDispatch ) + [ 'unlisten' ]( [ X_EVENT_PROGRESS, X_EVENT_SUCCESS, X_EVENT_ERROR ], X_NET_currentQueue, X_NET_proxyDispatch ) .reset(); + X_NET_currentQueue = X_NET_currentWrapper = X_NET_currentData = null; }; + console.log( '■■------------ X_NET_shiftQueue ' + X_NET_QUEUE_LIST.length ); + if( !X_NET_QUEUE_LIST.length ) return; - X_NET_currentQueue = X_NET_QUEUE_LIST.shift(); + + X_NET_currentQueue = q = X_NET_QUEUE_LIST.shift(); X_NET_currentData = X_Pair_get( X_NET_currentQueue ); switch( X_NET_currentData.netType ){ case X_NET_TYPE_XHR : - X_NET_currentWrapper = X_NET_XHRWrapper || X_TEMP.X_Net_XHR_init(); + + // TODO (xProtocol | method='update' | !cors) & canUse -> gadget.io.makeRequset, flash + // force 'gadget', 'flash' + switch( X_NET_currentData[ 'test' ] ){ + case 'gadget' : + X_NET_currentWrapper = X_GadgetXHR || X_TEMP.X_GadgetXHR_init(); + break; + case 'flash' : + break; + + default : + X_NET_currentWrapper = X_XHR || X_TEMP.X_XHR_init(); + }; + + + // OAuth2 + if( auth = X_NET_currentData[ 'auth' ] ){ + authSettings = X_Pair_get( auth ); + switch( auth[ 'state' ]() ){ + case 0 : + case 1 : + case 2 : + if( !( auth[ 'dispatch' ]( X_EVENT_NEED_AUTH ) & X_CALLBACK_PREVENT_DEFAULT ) ){ + // event 内で kill されていないことを確認 + if( X_NET_currentQueue === q ){ + authSettings.lazyRequests = authSettings.lazyRequests || []; + authSettings.lazyRequests.indexOf( q ) === -1 && authSettings.lazyRequests.push( q ); + X_NET_currentQueue = null; + X_NET_shiftQueue(); + }; + } else { + X_NET_currentQueue === q && q[ 'kill' ](); + }; + return; + case 3 : // refresh token + X_NET_QUEUE_LIST.push( X_NET_currentQueue ); + X_NET_currentQueue = null; + X_NET_shiftQueue(); + return; + }; + authSettings.updateRequest( auth, X_NET_currentData ); + }; break; case X_NET_TYPE_JSONP : - X_NET_currentWrapper = X_NET_JSONPWrapper || X_TEMP.X_NET_JSONP_init(); + X_NET_currentWrapper = X_JSONP || X_TEMP.X_JSONP_init(); break; case X_NET_TYPE_FORM : - X_NET_currentWrapper = X_NET_FormWrapper; + X_NET_currentWrapper = X_FormSender || X_TEMP.X_FormSender_init(); break; case X_NET_TYPE_IMAGE : - X_NET_currentWrapper = X_NET_ImageWrapper || X_TEMP.X_NET_Image_init(); - break; - case 5 : - X_NET_currentWrapper = X_NET_GIMRWrapper; + X_NET_currentWrapper = X_ImgLoader || X_TEMP.X_ImgLoader_init(); break; }; - X_NET_currentWrapper[ 'listen' ]( [ X_EVENT_PROGRESS, X_EVENT_SUCCESS, X_EVENT_ERROR, X_EVENT_TIMEOUT ], X_NET_currentQueue, X_NET_proxyDispatch ); + X_NET_currentWrapper[ 'listen' ]( [ X_EVENT_PROGRESS, X_EVENT_SUCCESS, X_EVENT_ERROR ], X_NET_currentQueue, X_NET_proxyDispatch ); X_NET_currentWrapper.load( X_NET_currentData ); };