OpenLayers OpenLayers

Ticket #964: wfs_request_abort.diff

File wfs_request_abort.diff, 20.8 kB (added by pgiraud, 1 year ago)
  • tests/Tile/test_WFS.html

    old new  
    2525        t.ok( tile.id != null, "tile is given an id"); 
    2626        t.ok( tile.events != null, "tile's events intitialized"); 
    2727    } 
    28  
    29     function test_Tile_WFS_requestSuccess(t) { 
    30         t.plan(1); 
    31         var layer = {}; // bogus layer 
    32         var position = new OpenLayers.Pixel(10,20); 
    33         var bounds = new OpenLayers.Bounds(1,2,3,4); 
    34         var url = "bobob"; 
    35         var size = new OpenLayers.Size(5,6); 
    36          
    37         tile = new OpenLayers.Tile.WFS(layer, position, bounds, url, size); 
    38         tile.destroy(); 
    39         tile.requestSuccess({'requestText': '<xml><foo /></xml>'}); 
    40         t.ok(true, "Didn't fail after calling requestSuccess on destroyed tile."); 
    41          
    42     } 
    4328     
    4429    function test_99_Tile_WFS_destroy(t) { 
    45         t.plan( 6 ); 
     30        t.plan( 8 ); 
    4631 
    4732        var layer = {}; // bogus layer 
    4833        var position = new OpenLayers.Pixel(10,20); 
     
    5439        tile.events.destroy = function() { 
    5540            t.ok(true, "tile events destroy() called"); 
    5641        }; 
    57  
    58   
     42         
     43        var _gAbort = false; 
     44        tile.request = { 
     45            transport: { 
     46                abort: function() { 
     47                    _gAbort = true; 
     48                } 
     49            } 
     50        } 
     51         
    5952        tile.destroy(); 
    6053 
    6154        t.ok(tile.layer == null, "tile.layer set to null"); 
     
    6457        t.ok(tile.position == null, "tile.position set to null"); 
    6558         
    6659        t.ok(tile.events == null, "tile.events set to null"); 
     60        t.ok(_gAbort, "request transport is aborted"); 
     61         
     62        tile.requestSuccess({'requestText': '<xml><foo /></xml>'}); 
     63        t.ok(true, "Didn't fail after calling requestSuccess on destroyed tile."); 
    6764    } 
    6865 
    6966  </script> 
  • lib/OpenLayers/Tile/WFS.js

    old new  
    2828     */ 
    2929    url: null, 
    3030     
     31    /** 
     32     * Property: request 
     33     * {OpenLayers.Ajax.Request} 
     34     */ 
     35    request: null, 
     36     
    3137    /** TBD 3.0 - reorder the parameters to the init function to put URL  
    3238     *             as last, so we can continue to call tile.initialize()  
    3339     *             without changing the arguments.  
     
    5763        this.destroyAllFeatures(); 
    5864        this.features = null; 
    5965        this.url = null; 
     66        if (this.request) { 
     67            this.request.transport.abort(); 
     68        } 
    6069    }, 
    6170 
    6271    /**  
     
    97106    * failure - {function} 
    98107    */ 
    99108    loadFeaturesForRegion:function(success, failure) { 
    100         OpenLayers.loadURL(this.url, null, this, success); 
     109        this.request = OpenLayers.loadURL(this.url, null, this, success); 
    101110    }, 
    102111     
    103112    /** 
  • lib/OpenLayers/Ajax.js

    old new  
    4949 * onFailure - {Function} callback for failure 
    5050 * 
    5151 * Both callbacks optional (though silly) 
     52 * 
     53 * Returns: 
     54 * {OpenLayers.Ajax.Request} - Created AJAX request 
    5255 */ 
    5356OpenLayers.loadURL = function(uri, params, caller, 
    5457                                  onComplete, onFailure) { 
     
    6467                           : OpenLayers.nullHandler; 
    6568 
    6669    // from prototype.js 
    67     new OpenLayers.Ajax.Request(uri,  
     70    return new OpenLayers.Ajax.Request(uri,  
    6871                     {   method: 'get',  
    6972                         parameters: params, 
    7073                         onComplete: success,  
     
    135138     */ 
    136139    getTransport: function() { 
    137140        return OpenLayers.Util.Try( 
     141            function() {return new XMLHttpRequest();}, 
    138142            function() {return new ActiveXObject('Msxml2.XMLHTTP');}, 
    139             function() {return new ActiveXObject('Microsoft.XMLHTTP');}, 
    140             function() {return new XMLHttpRequest();} 
     143            function() {return new ActiveXObject('Microsoft.XMLHTTP');} 
    141144        ) || false; 
    142145    }, 
    143146 
     
    167170     * responderToAdd - {?} 
    168171     */ 
    169172    register: function(responderToAdd) { 
    170       for (var i = 0; i < this.responders.length; i++){ 
    171           if (responderToAdd == this.responders[i]){ 
    172               return; 
    173          
    174      
    175       this.responders.push(responderToAdd); 
     173        for (var i = 0; i < this.responders.length; i++){ 
     174            if (responderToAdd == this.responders[i]){ 
     175                return; 
     176           
     177       
     178        this.responders.push(responderToAdd); 
    176179    }, 
    177180 
    178181    /** 
     182     * Method: unregister 
     183     *   
     184     * Parameters: 
     185     * responderToRemove - {?} 
     186     */ 
     187    register: function(responderToRemove) { 
     188        OpenLayers.Util.removeItem(responderToRemove); 
     189    }, 
     190 
     191    /** 
    179192     * Method: dispatch 
    180193     *  
    181194     * Parameters: 
    182195     * callback - {?} 
    183196     * request - {?} 
    184197     * transport - {?} 
    185      * json - {?} 
    186198     */ 
    187     dispatch: function(callback, request, transport, json) { 
     199    dispatch: function(callback, request, transport) { 
    188200        var responder; 
    189201        for (var i = 0; i < this.responders.length; i++) { 
    190202            responder = this.responders[i]; 
     
    193205                typeof responder[callback] == 'function') { 
    194206                try { 
    195207                    responder[callback].apply(responder,  
    196                                               [request, transport, json]); 
     208                                              [request, transport]); 
    197209                } catch (e) {} 
    198210            } 
    199211        } 
     
    217229}); 
    218230 
    219231/** 
    220  * Namespace: OpenLayers.Ajax.Base 
    221  * {Object} 
     232 * Class: OpenLayers.Ajax.Base 
    222233 */ 
    223 OpenLayers.Ajax.Base = function() {}; 
    224 OpenLayers.Ajax.Base.prototype = { 
    225  
     234OpenLayers.Ajax.Base = OpenLayers.Class({ 
     235       
    226236    /** 
     237     * Constructor: OpenLayers.Ajax 
     238     *  
     239     * Parameters:  
     240     * options - {Object} 
     241     */ 
     242    /** 
    227243     * Function: setOptions 
    228244     *  
    229245     * Parameters: 
    230246     * options - {Object} 
    231247     */ 
    232     setOptions: function(options) { 
     248    initialize: function(options) { 
    233249        this.options = { 
    234             'method': 'post', 
    235             'asynchronous': true, 
    236             'parameters': '' 
     250            method:       'post', 
     251            asynchronous: true, 
     252            contentType:  'application/x-www-form-urlencoded', 
     253            encoding:     'UTF-8', 
     254            parameters:   '' 
    237255        }; 
    238256        OpenLayers.Util.extend(this.options, options || {}); 
    239     }, 
    240  
    241     /** 
    242      * Function: responseIsSuccess 
    243      *  
    244      * Returns: 
    245      * {Boolean} 
    246      */ 
    247     responseIsSuccess: function() { 
    248         return this.transport.status == undefined ||  
    249                this.transport.status == 0 ||  
    250                (this.transport.status >= 200 && this.transport.status < 300); 
    251     }, 
    252  
    253     /** 
    254      * Function: responseIsFailure 
    255      *  
    256      * Returns: 
    257      * {Boolean} 
    258      */ 
    259     responseIsFailure: function() { 
    260         return !this.responseIsSuccess(); 
     257         
     258        this.options.method = this.options.method.toLowerCase(); 
     259         
     260        if (typeof this.options.parameters == 'string') { 
     261            this.options.parameters =  
     262                OpenLayers.Util.getParameters(this.options.parameters); 
     263        } 
    261264    } 
    262 }
     265})
    263266 
    264  
    265267/** 
    266268 * Class: OpenLayers.Ajax.Request 
    267269 * 
     
    269271 *  - <OpenLayers.Ajax.Base> 
    270272 */ 
    271273OpenLayers.Ajax.Request = OpenLayers.Class(OpenLayers.Ajax.Base, { 
     274 
     275    /** 
     276     * Property: _complete 
     277     * 
     278     * {Boolean} 
     279     */ 
     280    _complete: false, 
    272281       
    273       /** 
    274        * Constructor: OpenLayers.Ajax.Request 
    275        *  
    276        * Parameters:  
    277        * url - {String} 
    278        * options - {Object} 
    279        */ 
     282    /** 
     283     * Constructor: OpenLayers.Ajax.Request 
     284     *  
     285     * Parameters:  
     286     * url - {String} 
     287     * options - {Object} 
     288     */ 
    280289    initialize: function(url, options) { 
     290        OpenLayers.Ajax.Base.prototype.initialize.apply(this, [options]); 
     291         
    281292        this.transport = OpenLayers.Ajax.getTransport(); 
    282         this.setOptions(options); 
    283293        this.request(url); 
    284294    }, 
    285295 
     
    290300     * url - {String} 
    291301     */ 
    292302    request: function(url) { 
    293         var parameters = this.options.parameters || ''; 
    294         if (parameters.length > 0) { 
    295             parameters += '&_='; 
     303        this.url = url; 
     304        this.method = this.options.method; 
     305        var params = OpenLayers.Util.extend({}, this.options.parameters); 
     306         
     307        if (this.method != 'get' && this.method != 'post') { 
     308            // simulate other verbs over post 
     309            params['_method'] = this.method; 
     310            this.method = 'post'; 
    296311        } 
     312 
     313        this.parameters = params;         
     314         
     315        if (params = OpenLayers.Util.getParameterString(params)) { 
     316            // when GET, append parameters to URL 
     317            if (this.method == 'get') { 
     318                this.url += (this.url.include('?') ? '&' : '?') + params; 
     319            } else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { 
     320                params += '&_='; 
     321            } 
     322        } 
    297323        try { 
    298             this.url = url
    299             if (this.options.method == 'get' && parameters.length > 0) { 
    300                this.url += (this.url.match(/\?/) ? '&' : '?') + parameters
     324            var response = new OpenLayers.Ajax.Response(this)
     325            if (this.options.onCreate) { 
     326                this.options.onCreate(response)
    301327            } 
    302328             
    303329            OpenLayers.Ajax.Responders.dispatch('onCreate',  
    304330                                                this,  
    305                                                 this.transport); 
     331                                                response); 
    306332     
    307             this.transport.open(this.options.method,  
     333            this.transport.open(this.method.toUpperCase(),  
    308334                                this.url, 
    309335                                this.options.asynchronous); 
    310336     
    311337            if (this.options.asynchronous) { 
    312                 setTimeout(OpenLayers.Function.bind
    313                     (function() {this.respondToReadyState(1);}),this), 10 
    314                 ); 
     338                window.setTimeout
     339                    OpenLayers.Function.bind(this.respondToReadyState, this), 
     340                    1000); 
    315341            } 
    316342             
    317343            this.transport.onreadystatechange =  
    318344                OpenLayers.Function.bind(this.onStateChange, this);     
    319345            this.setRequestHeaders(); 
    320346     
    321             var body = this.options.postBody ? this.options.postBody  
    322                                              : parameters
    323             this.transport.send(this.options.method == 'post' ? body : null); 
     347            this.body =  this.method == 'post' ? 
     348                (this.options.postBody || params) : null
     349            this.transport.send(this.body); 
    324350     
    325351            // Force Firefox to handle ready state 4 for synchronous requests 
    326352            if (!this.options.asynchronous &&  
    327353                this.transport.overrideMimeType) { 
    328                  
    329354                this.onStateChange(); 
    330355            } 
    331      
    332356        } catch (e) { 
    333357            this.dispatchException(e); 
    334358        } 
    335359    }, 
     360 
     361    /** 
     362     * Method: onStateChange 
     363     */ 
     364    onStateChange: function() { 
     365        var readyState = this.transport.readyState; 
     366        if (readyState > 1 && !((readyState == 4) && this._complete)) { 
     367            this.respondToReadyState(this.transport.readyState); 
     368        } 
     369    }, 
    336370      
    337371    /** 
    338372     * Method: setRequestHeaders 
    339373     */ 
    340374    setRequestHeaders: function() { 
    341         var requestHeaders = [ 
    342             'X-Requested-With', 
    343             'XMLHttpRequest', 
    344             'X-Prototype-Version', 
    345             'OpenLayers' 
    346         ]; 
     375        var headers = { 
     376            'X-Requested-With': 'XMLHttpRequest', 
     377            'Accept': 'text/javascript, text/html, application/xml, text/xml, */*', 
     378            'OpenLayers': true 
     379        }; 
     380 
     381        if (this.method == 'post') { 
     382            headers['Content-type'] = this.options.contentType + 
     383                (this.options.encoding ? '; charset=' + this.options.encoding : ''); 
    347384     
    348         if (this.options.method == 'post' && !this.options.postBody) { 
    349             requestHeaders.push('Content-type', 
    350                                 'application/x-www-form-urlencoded'); 
    351      
    352             // Force "Connection: close" for Mozilla browsers to work around 
    353             // a bug where XMLHttpReqeuest sends an incorrect Content-length 
    354             // header. See Mozilla Bugzilla #246651. 
    355             if (this.transport.overrideMimeType) { 
    356                 requestHeaders.push('Connection', 'close'); 
     385            /* Force "Connection: close" for older Mozilla browsers to work 
     386             * around a bug where XMLHttpRequest sends an incorrect 
     387             * Content-length header. See Mozilla Bugzilla #246651. 
     388             */ 
     389            if (this.transport.overrideMimeType && 
     390                (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) { 
     391                headers['Connection'] = 'close'; 
    357392            } 
    358393        } 
    359      
    360         if (this.options.requestHeaders) { 
    361             requestHeaders.push.apply(requestHeaders,  
    362                                       this.options.requestHeaders); 
     394        // user-defined headers 
     395        if (typeof this.options.requestHeaders == 'object') {     
     396            var extras = this.options.requestHeaders; 
     397             
     398            if (typeof extra.push == 'function') { 
     399                for (var i = 0, length = extras.length; i < length; i += 2) { 
     400                    headers[extras[i]] = extras[i+1]; 
     401                } 
     402            } else { 
     403                for (var i in extras) { 
     404                    headers[i] = pair[i]; 
     405                } 
     406            } 
    363407        } 
    364            
    365         for (var i = 0; i < requestHeaders.length; i += 2) { 
    366             this.transport.setRequestHeader(requestHeaders[i],  
    367                                             requestHeaders[i+1]); 
     408         
     409        for (var name in headers) { 
     410            this.transport.setRequestHeader(name, headers[name]); 
    368411        } 
    369412    }, 
    370  
     413     
    371414    /** 
    372      * Method: onStateChange 
    373      */ 
    374     onStateChange: function() { 
    375         var readyState = this.transport.readyState; 
    376         if (readyState != 1) { 
    377           this.respondToReadyState(this.transport.readyState); 
    378         } 
    379     }, 
    380  
    381     /**  
    382      * Method: header 
    383      *  
     415     * Method: success 
     416     * 
    384417     * Returns: 
    385      * {?} 
     418     * {Boolean} -  
    386419     */ 
    387     header: function(name) { 
    388         try { 
    389             return this.transport.getResponseHeader(name); 
    390         } catch (e) {} 
     420    success: function() { 
     421        var status = this.getStatus(); 
     422        return !status || (status >=200 && status < 300); 
    391423    }, 
    392  
    393     /**  
    394      * Method: evalJSON 
    395      *  
     424     
     425    /** 
     426     * Method: getStatus 
     427     * 
    396428     * Returns: 
    397      * {?} 
     429     * {Integer} - Status 
    398430     */ 
    399     evalJSON: function() { 
     431    getStatus: function() { 
    400432        try { 
    401             return eval(this.header('X-JSON')); 
    402         } catch (e) {} 
    403     }, 
    404  
    405     /** 
    406      * Method: evalResponse 
    407      *  
    408      * Returns:  
    409      * {?} 
    410      */ 
    411     evalResponse: function() { 
    412         try { 
    413             return eval(this.transport.responseText); 
     433            return this.transport.status || 0; 
    414434        } catch (e) { 
    415             this.dispatchException(e); 
     435            return 0 
    416436        } 
    417437    }, 
    418438 
     
    423443     * readyState - {?} 
    424444     */ 
    425445    respondToReadyState: function(readyState) { 
    426         var event = OpenLayers.Ajax.Request.Events[readyState]; 
    427         var transport = this.transport, json = this.evalJSON(); 
     446        var state = OpenLayers.Ajax.Request.Events[readyState]; 
     447        var response = new OpenLayers.Ajax.Response(this); 
    428448     
    429         if (event == 'Complete') { 
     449        if (state == 'Complete') { 
    430450            try { 
    431                 var responseSuccess = this.responseIsSuccess() ? 'Success' 
    432                                                                 : 'Failure'; 
    433                                                                   
    434                 (this.options['on' + this.transport.status] || 
    435                  this.options['on' + responseSuccess] || 
    436                  OpenLayers.Ajax.emptyFunction)(transport, json); 
     451                this._complete = true; 
     452                (this.options['on' + response.status] || 
     453                    this.options['on' + (this.success() ? 'Success' : 'Failure')] || 
     454                    OpenLayers.Ajax.emptyFunction)(response); 
    437455            } catch (e) { 
    438456                this.dispatchException(e); 
    439457            } 
    440458     
    441             var contentType = this.header('Content-type') || ''; 
    442             if (contentType.match(/^text\/javascript/i)) { 
    443                 this.evalResponse(); 
    444             } 
     459            var contentType = response.getHeader('Content-type'); 
    445460        } 
    446461     
    447462        try { 
    448             (this.options['on' + event] ||  
    449              OpenLayers.Ajax.emptyFunction)(transport, json); 
    450              OpenLayers.Ajax.Responders.dispatch('on' + event,  
     463            (this.options['on' + state] ||  
     464             OpenLayers.Ajax.emptyFunction)(response); 
     465             OpenLayers.Ajax.Responders.dispatch('on' + state,  
    451466                                                 this,  
    452                                                  transport,  
    453                                                  json); 
     467                                                 response); 
    454468        } catch (e) { 
    455469            this.dispatchException(e); 
    456470        } 
    457471     
    458         // Avoid memory leak in MSIE: clean up the oncomplete event handler 
    459         if (event == 'Complete') { 
     472        if (state == 'Complete') { 
     473            // avoid memory leak in MSIE: clean up 
    460474            this.transport.onreadystatechange = OpenLayers.Ajax.emptyFunction; 
    461475        } 
    462476    }, 
     477     
     478    /** 
     479     * Method: getHeader 
     480     *  
     481     * Parameters: 
     482     * name - {String} Header name 
     483     * 
     484     * Returns: 
     485     * {?} - response header for the given name 
     486     */ 
     487    getHeader: function(name) { 
     488        try { 
     489            return this.transport.getResponseHeader(name); 
     490        } catch (e) { 
     491            return null 
     492        } 
     493    }, 
    463494 
    464495    /** 
    465496     * Method: dispatchException 
     
    468499     * exception - {?} 
    469500     */ 
    470501    dispatchException: function(exception) { 
    471         if (this.options.onException) { 
    472             this.options.onException(this, exception); 
    473         } else { 
    474             // if we get here, Responders.dispatch('onException') will never 
    475             // be called. too bad. we should probably take out the Responders 
    476             // stuff anyway. 
    477             throw exception; 
    478         } 
     502        (this.options.onException || 
     503            OpenLayers.Ajax.emptyFunction)(this, exception); 
    479504        OpenLayers.Ajax.Responders.dispatch('onException', this, exception); 
    480505    } 
    481      
    482506}); 
    483507 
    484508/**  
     
    489513  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; 
    490514 
    491515/** 
     516 * Class: OpenLayers.Ajax.Request 
     517 * 
     518 * Inherit: 
     519 *  - <OpenLayers.Ajax.Base> 
     520 */ 
     521OpenLayers.Ajax.Response = OpenLayers.Class({ 
     522 
     523    /** 
     524     * Property: status 
     525     * 
     526     * {Integer} 
     527     */ 
     528    status: 0, 
     529     
     530 
     531    /** 
     532     * Property: statusText 
     533     * 
     534     * {String} 
     535     */ 
     536    statusText: '', 
     537       
     538    /** 
     539     * Constructor: OpenLayers.Ajax.Response 
     540     *  
     541     * Parameters:  
     542     * request - {Object} 
     543     */ 
     544    initialize: function(request) { 
     545        this.request = request; 
     546        var transport = this.transport = request.transport, 
     547            readyState = this.readyState = transport.readyState; 
     548         
     549        if ((readyState > 2 && 
     550            !(!!(window.attachEvent && !window.opera))) || 
     551            readyState == 4) { 
     552            this.status       = this.getStatus(); 
     553            this.statusText   = this.getStatusText(); 
     554            this.responseText = transport.responseText == null ? 
     555                '' : String(transport.responseText); 
     556        } 
     557         
     558        if(readyState == 4) { 
     559            var xml = transport.responseXML; 
     560            this.responseXML  = xml === undefined ? null : xml; 
     561        } 
     562    }, 
     563     
     564    /** 
     565     * Method: getStatus 
     566     */ 
     567    getStatus: OpenLayers.Ajax.Request.prototype.getStatus, 
     568     
     569    /** 
     570     * Method: getStatustext 
     571     * 
     572     * Returns: 
     573     * {String} - statusText 
     574     */ 
     575    getStatusText: function() { 
     576        try { 
     577            return this.transport.statusText || ''; 
     578        } catch (e) { 
     579            return ''; 
     580        } 
     581    }, 
     582     
     583    /** 
     584     * Method: getHeader 
     585     */ 
     586    getHeader: OpenLayers.Ajax.Request.prototype.getHeader, 
     587     
     588    /**  
     589     * Method: getResponseHeader 
     590     * 
     591     * Returns: 
     592     * {?} - response header for given name 
     593     */ 
     594    getResponseHeader: function(name) { 
     595        return this.transport.getResponseHeader(name); 
     596    } 
     597}); 
     598 
     599 
     600/** 
    492601 * Function: getElementsByTagNameNS 
    493602 *  
    494603 * Parameters: