1. #21
    Sencha - Community Support Team hendricd's Avatar
    Join Date
    Aug 2007
    Location
    Long Island, NY USA
    Posts
    5,963
    Vote Rating
    10
    hendricd will become famous soon enough hendricd will become famous soon enough

      0  

    Smile


    Quote Originally Posted by ambience View Post
    ....I am forced to rely on Prototypes asynchronous request support.
    You mean 'synchronous' request support, right?

    As I posted previously, this is availabe for Ext here.
    "be dom-ready..."
    Doug Hendricks

    Maintaining ux: ManagedIFrame, MIF2 (FAQ, Wiki), ux.Media/Flash, AudioEvents, ux.Chart[Fusion,OFC,amChart], ext-basex.js/$JIT, Documentation Site.


    Got Sencha licensing questions? Find out more here.


  2. #22
    Ext User jclawson's Avatar
    Join Date
    Mar 2007
    Location
    Denver, Colorado
    Posts
    145
    Vote Rating
    1
    jclawson is on a distinguished road

      0  

    Default


    I am a bit disappointed in the Ext folks here. Most of the time calls should be asynchronous, but to purposefully design away the ability to make synchronous calls is naive at best. There are times and situations where asynchronous just will not do, many of which have already been highlighted here.

    Quote Originally Posted by hendricd View Post
    You mean 'synchronous' request support, right?
    As I posted previously, this is availabe for Ext here.
    Hendricd... Your code is a little difficult to understand. It doesn't look like it was purpose built for Sync requests.

    From the way I see it, it appears that one would have to patch both the Connection.js and all the bindings in order to achieve synchronous requests.

    Perhaps you can explain your methodology.

  3. #23
    Sencha - Community Support Team hendricd's Avatar
    Join Date
    Aug 2007
    Location
    Long Island, NY USA
    Posts
    5,963
    Vote Rating
    10
    hendricd will become famous soon enough hendricd will become famous soon enough

      0  

    Post Sure. I'll give this a shot...

    Sure. I'll give this a shot...


    Perhaps you can explain your methodology.
    To review: XMLHttpRequest (herein XHR) behaviour:
    • A synchronous call blocks the browser's current execution thread until complete.
    • There are no timeouts.

    [All dry stuff here, but:]
    The Ext.data.Connection class was designed with an 'event-model' in mind. That 'event-model' is inherent in every Ext component/widget. That event-model implies asynchonous XHR support for interaction with data sources, because without support for a 'timeout', these components/widgets would 'appear' to lock up during a long-running server response. From a UI perspective that is King! Kudos: Jack !

    Ext.lib.Ajax, on the other hand, is the work-horse of the entire AJAX framework. I targeted these enhancements to this area because:
    • The 'event-driven' expectations of it's consumers (Ext components/widgets/dataStores and data.Connection) must be preserved.
    • The success of an Ajax request throughout the framework is predicated on evaluation of HTTP status codes at the lib.Ajax level. XHR returns a status of (0) for local file systems. Ext, out-of-the-box, considers that a failure. Wanted that/need that to change
    • For async calls, Ext uses a poll-timer to monitor the progress of the call. If it's taking to long, the timeout event trickles up the chain to event subscribers. data.Connection (an abstraction layer) could care less about these timers, as its event model simply responds to the few events that lib.Ajax generates. For synchronous support, there is no need for such timers because they won't run because the browser context is blocked. You finally get a response when the browser gives up. Again, IMO data.Connection was/is not the proper place for these mods.
    • IE7 (as you may know) introduced it's own native (vs ActiveX) XHR API, and it's own set of problems (not addressing all those here ). The override also gives you a choice of which implementation to use.
    • The XHR open, send methods are wrapped (and raise appropriate exceptions) when the browser barks about security and other issues. The response object status is enriched to indicate what the problem was -- didn't have that before.
    • It also adds UserId and password auth support for XHR.

    So, yes, it may appear that the structure of localXHR.js (and the naming convention is likely ambiguous) was based on 'after-thought'. I assure all who use it -- it was not. It was re-factored to account for the issues mentioned earlier and more.

    That said, two no, three design consideration stands out from all others:

    1) Preserve Ext components/widgets thirst for events, whether async or sync. That's why the event model still works regardless.
    2) data.Connection is not part of the Core, it's a package (you'll likely want to load later ).
    3) data.Connection gets sub-classed a lot. lib.Ajax is core, so all components benefit.

    The last example on this thread uses the event-based approach (even though the requests are made synchronously) to demonstrate that you can stick with UI-events in your App even though you are blocking the browser every time you do so.

    Keep in mind -- for a synchronous request, the response object is also returned immediately by the call to lib.Ajax.request() upon completion (which means it's also returned to data.Connection if you want to deal with it on that level).

    So, for all you synchronous-js-loader-wannebees, this is now possible:

    Code:
    <head>
    <link rel="stylesheet" type="text/css" href="src/resources/css/ext-all.css" />
    <script type="text/javascript" id="ext-base" src="src/ext-base.js"></script>
    <script type="text/javascript" src="src/localXHR.js"></script>
    <script type="text/javascript">
    Ext.ux.ModuleManager = function(config){
        
        Ext.ux.ModuleManager.superclass.constructor.call(this,config);
        
        this.asynchronous  = false;    
        
        Ext.apply(this,config||{},{modulePath:function(){  //based on current page
    			   var d= location.href.indexOf('\/') != -1 ? '\/':'\\';
    			   var u=location.href.split(d);
    			   u.pop(); //this page
    			   return u.join(d) + d;	
         			  }()} );
        
        this.modules = {};
        
        this.addEvents({
                /**
                * @event loadexception
                * Fires when any exception is raised
                * returning false prevents any subsequent pending module load requests
                * @param {Ext.ux.ModuleManager} this
                * @param {String} module -- the module name
                * @param {Object} error -- An error object containing: httpStatus, httpStatusText, error object
                */
                "loadexception" : true,
                /**
    	   * @event alreadyloaded
    	   * Fires when the ModuleManager determines that the requested module has already been loaded
    	   * @param {Ext.ux.ModuleManager} this
               * @param {String} module -- the module name
    	   */
                "alreadyloaded" : true,
        	   /**
                * @event load
                * Fires when the retrieved content has been successfully evaled into the current context.
                * @param {Ext.ux.ModuleManager} this
                * @param {String} module -- the module name
                */
                "load" : true,
                /**
                 * @event beforeload
                 * Fires when the request has successfully completed and just prior to eval
                 * returning false prevents the content (of this module) from being loaded (eval'ed)
                 * @param {Ext.ux.ModuleManager} this
                 * @param {String} module -- the module name
                 * @param {Object} response - the Ajax response object
                 */
                "beforeload" : true
                
        });
     
    };
    
    Ext.extend(Ext.ux.ModuleManager,Ext.util.Observable,{
    
    loaded:function(name){
      return this.modules[name]===true;
    }
    ,load:function(){
      var result = true
         ,keepItUp = true
         ,StopIter = new Error("StopIteration")
         ,reqOptions = {
    	    method:this.method||'GET'
    	   ,async:this.asynchronous
    	   ,url:null
    	   ,success:function(response,options){
    		try{
    			if(this.fireEvent('beforeload', this, options.module, response) !== false){
    			     	this.globalEval( response.responseText );
    			     	this.modules[options.module]=true;
    			   	this.fireEvent('load', this, options.module);
    			}
    			
    		}catch(ex) {
    		   keepItUp = this.fireEvent('loadexception', this, options.module,{ 
    		        error         :ex
    		       ,httpStatus    :response.status
    		       ,httpStatusText:response.statusText
    		       });
    		       
    		      result = false; 
    
    		}
    
    	   }
    	   ,failure:function(response,options){
    	   	keepItUp = this.fireEvent('loadexception', this, options.module,{ 
    		        error         :response.stat.error
    		       ,httpStatus    :response.status
    		       ,httpStatusText:response.statusText
    		       });
    	   	
    	   	result = false;
    	   	
    	   }
    	   ,scope:this
    	 };
       
     /* Iterate the desired modules in there implied dependency order */
    try{ 
         var mm = this;
         Ext.each(arguments , function(module){
             var fullModule = module.indexOf('.')>-1?module:module + '.js';
             var opt=Ext.apply({},{url:mm.modulePath + fullModule ,module:module},reqOptions);
         		  
             if(!mm.loaded(module)){
               Ext.Ajax.request(opt);
             } else {
               keepItUp = mm.fireEvent('alreadyloaded', mm, module);
             }
             if(keepItUp===false)throw StopIter;
          });
    
    } catch(ex){ if (ex != StopIter)throw ex; }
    
      
      return result;
    }
    ,globalEval: function( data , scope ) {
    	scope || (scope = window);
    	if ( scope.execScript )
    		scope.execScript( data );
    	else if ( Ext.isSafari )
    		// safari doesn't provide a synchronous global eval
    		scope.setTimeout( data, 0 );
    	else
    		eval.call( scope, data );
        }
    });
    
    Ext.ModuleManager=new Ext.ux.ModuleManager({});
    Ext.ModuleManager.modulePath += 'packages/';
    Ext.ModuleManager.on({  //setup a default beforeload handler to verify Content-Type header
    		'beforeload':function(manager, module, response){
    		        // response.responseText may be analyzed/modified at this point.
    			return response.stat.isLocal || 
    			   (response.getResponseHeader['Content-Type']||'').indexOf('javascript')!=-1;
    		//return false to prevent the script from being evaled.
    		}
    		,scope:Ext.ModuleManager
    		});
    
    //Now call your global loader anything you want:		
    Ext.require = Ext.ModuleManager.load.createDelegate(Ext.ModuleManager);
    
    if(!Ext.require('core','dragdrop','menu','data','grid','ux/widget','ovr/custom.js')){panic()};
    </script>
    </head>
    Clear as ?

    Footnote: There are a few Asynch design patterns that would accomplish the same thing, but that's another story -- and much debate.
    I'll bow out on that one though.
    Last edited by hendricd; 16 Sep 2007 at 4:34 AM. Reason: Replaced Example with ux version that actually works!
    "be dom-ready..."
    Doug Hendricks

    Maintaining ux: ManagedIFrame, MIF2 (FAQ, Wiki), ux.Media/Flash, AudioEvents, ux.Chart[Fusion,OFC,amChart], ext-basex.js/$JIT, Documentation Site.


    Got Sencha licensing questions? Find out more here.


  4. #24
    Sencha - Community Support Team hendricd's Avatar
    Join Date
    Aug 2007
    Location
    Long Island, NY USA
    Posts
    5,963
    Vote Rating
    10
    hendricd will become famous soon enough hendricd will become famous soon enough

      0  

    Thumbs up


    [Update]

    The previous post now includes a fully functional js module loader.

    I'll be ux.packaging it up and expanding docs on it soon.

    Enjoy.
    "be dom-ready..."
    Doug Hendricks

    Maintaining ux: ManagedIFrame, MIF2 (FAQ, Wiki), ux.Media/Flash, AudioEvents, ux.Chart[Fusion,OFC,amChart], ext-basex.js/$JIT, Documentation Site.


    Got Sencha licensing questions? Find out more here.


  5. #25
    Ext User pierrot's Avatar
    Join Date
    Aug 2007
    Location
    Toulouse (France)
    Posts
    3
    Vote Rating
    0
    pierrot is on a distinguished road

      0  

    Default


    Quote Originally Posted by brian.moeskau View Post
    AJAX == Asynchronous JavaScript And Xml
    Just back from AJAX-World conf', it was a great event . Anyway, as a matter of fact when Jesse James Garrett came up with the term "AJAX" he did not mean for it to be an acronym for sure... So, from historical point of view AJAX was Ajax, just, not "Asynchronous blablabla"

    Cheers.
    Necessity is the Mother of invention

  6. #26
    Sencha User
    Join Date
    Apr 2012
    Location
    Austin, Texas
    Posts
    4
    Vote Rating
    0
    brian.moeskau is an unknown quantity at this point

      0  

    Default


    Here's his original essay:

    http://www.adaptivepath.com/ideas/es...ves/000385.php

    Defining Ajax... "asynchronous data retrieval using XMLHttpRequest;"

    If you read the article, he specifically contrasts the classic synchronous model with the new Ajax asynchronous model.


  7. #27
    Ext User pierrot's Avatar
    Join Date
    Aug 2007
    Location
    Toulouse (France)
    Posts
    3
    Vote Rating
    0
    pierrot is on a distinguished road

      0  

    Default


    Quote Originally Posted by brian.moeskau View Post
    Here's his original essay:

    http://www.adaptivepath.com/ideas/es...ves/000385.php

    Defining Ajax... "asynchronous data retrieval using XMLHttpRequest;"

    If you read the article, he specifically contrasts the classic synchronous model with the new Ajax asynchronous model.

    Hi Brian,

    I feel you jumped too quickly on this, I was not arguing about the asynchronous side of the story but rather the fact Ajax was originally not an acronym but simply a name for a set of technologies coming together.. I am an old fox who likes to call things in the right way

    Cheers.
    Necessity is the Mother of invention

  8. #28
    Sencha User
    Join Date
    Apr 2012
    Location
    Austin, Texas
    Posts
    4
    Vote Rating
    0
    brian.moeskau is an unknown quantity at this point

      0  

    Default


    I was just playing devil's advocate. The context of this thread is a debate on whether or not synchronous calls are useful in Ajax, so I read your post in that light.

  9. #29
    Sencha User
    Join Date
    Mar 2007
    Posts
    22
    Vote Rating
    0
    jakeonthenet is on a distinguished road

      0  

    Default


    In my humble opinion sync. javascript calls are bad for one reason: they block the UI thread, and give the user the impression the browser/app is frozen. This is bad UI design.

  10. #30
    Ext JS Premium Member ambience's Avatar
    Join Date
    Mar 2007
    Location
    Denver, CO
    Posts
    136
    Vote Rating
    0
    ambience is on a distinguished road

      0  

    Default


    95% of the time you would be correct; but a framework as well designed as Ext should provide some form of synchronous access for the other 5%. It can be undocumented, a bit out of the way, anything to keep people who don't know any better from using it. However, it should exist.