X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=0.6.x%2Fjs%2F06_net%2F00_XNet.js;h=3e7b4543393872f9baf25458cfcba06c375c4b53;hb=HEAD;hp=7d6393c4be228b3e4553d86afaa50f303d6273b7;hpb=326aa8b45801298cafb13d4fd367cd240cfc4abc;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 7d6393c..3e7b454 100644 --- a/0.6.x/js/06_net/00_XNet.js +++ b/0.6.x/js/06_net/00_XNet.js @@ -7,30 +7,31 @@ /** - *

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

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

通信のキャンセル

- *

kill() で通信待ち中はキャンセル&破棄、通信中の場合は通信の中断&破棄を行う。SUCCESS, ERROR, TIMEOUT イベント以降は kill() は無視される。 + *

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

イベント

*
*
X.Event.PROGRESS
通信進行状況 *
X.Event.SUCCESS
通信成功 - *
X.Event.ERROR
通信エラー - *
X.Event.TIMEOUT
通信タイムアウト - *
X.Event.CANCELED
通信のユーザー、プログラムによるキャンセル - *
X.Event.COMPLETE
通信完了。SUCCESS, ERROR, TIMEOUT, CANCELED 後に発生。 + *
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', 'image', 'img' + *
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 認証 @@ -41,6 +42,25 @@ *
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 @@ -52,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 } ); @@ -67,58 +93,45 @@ X[ 'Net' ] = X_EventDispatcher[ 'inherits' ]( 'X.Net', X_Class.NONE, { - 'netType' : '', - 'netName' : '', - 'netVersion' : 0, '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; - }; - url = opt[ 'url' ]; + //}+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; @@ -129,41 +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 ); - opt.netType = type; - opt[ 'url' ] = url; + 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プロトコル な binary のロード -> gadget 内で proxyURL による XHR + // xプロトコル(X_URL_isSameProtocol) な binary のロード -> gadget 内で proxyURL による XHR // or X_EVENT_ERROR opt[ 'dataType' ] = opt[ 'dataType' ] || X_URL_getEXT( url ); }; + 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; } } ); @@ -181,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, @@ -198,20 +236,23 @@ function X_NET_proxyDispatch( e ){ 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; }; @@ -228,73 +269,87 @@ function X_NET_proxyDispatch( e ){ case X_EVENT_ERROR : if( e.status === 401 ){ if( auth = X_Pair_get( this )[ 'auth' ] ){ - X_Pair_get( auth ).onAuthError( auth ); + X_Pair_get( auth ).onAuthError( auth, e ); + // TODO 破棄しないで待機。 }; }; case X_EVENT_SUCCESS : - 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 } ); + X_NET_completePhase = 1; + this[ 'listenOnce' ]( X_EVENT_COMPLETE, X_NET_proxyDispatch ) + [ 'asyncDispatch' ]( 32, { type : X_EVENT_COMPLETE, 'lastEventType' : e.type } ); + + // target を上書き X_NET_currentWrapper -> X_NET_currentQueue + e[ 'target' ] = e[ 'currentTarget' ] = this; + 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(){ - var auth, authSettings; +// 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 : - // TODO (xProtocol | method) & canUse -> gadget.io.makeRequset, flash + // TODO (xProtocol | method='update' | !cors) & canUse -> gadget.io.makeRequset, flash // force 'gadget', 'flash' switch( X_NET_currentData[ 'test' ] ){ case 'gadget' : - X_NET_currentWrapper = X_NET_GIMRWrapper || X_TEMP.X_Net_GIMR_init(); + X_NET_currentWrapper = X_GadgetXHR || X_TEMP.X_GadgetXHR_init(); break; case 'flash' : break; + default : - X_NET_currentWrapper = X_NET_XHRWrapper || X_TEMP.X_Net_XHR_init(); + 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() ){ + switch( auth[ 'state' ]() ){ case 0 : case 1 : - if( !( auth[ 'dispatch' ]( X_EVENT_NEED_AUTH ) & X_Callback_PREVENT_DEFAULT ) ){ - authSettings.lazyReq = X_NET_currentQueue; + 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' ](); }; - X_NET_currentQueue = null; - X_NET_shiftQueue(); - break; - case 2 : // refresh token + return; + case 3 : // refresh token X_NET_QUEUE_LIST.push( X_NET_currentQueue ); X_NET_currentQueue = null; X_NET_shiftQueue(); @@ -304,20 +359,17 @@ function X_NET_shiftQueue(){ }; 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 ); };