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 25 25 t.ok( tile.id != null, "tile is given an id"); 26 26 t.ok( tile.events != null, "tile's events intitialized"); 27 27 } 28 29 function test_Tile_WFS_requestSuccess(t) {30 t.plan(1);31 var layer = {}; // bogus layer32 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 }43 28 44 29 function test_99_Tile_WFS_destroy(t) { 45 t.plan( 6);30 t.plan( 8 ); 46 31 47 32 var layer = {}; // bogus layer 48 33 var position = new OpenLayers.Pixel(10,20); … … 54 39 tile.events.destroy = function() { 55 40 t.ok(true, "tile events destroy() called"); 56 41 }; 57 58 42 43 var _gAbort = false; 44 tile.request = { 45 transport: { 46 abort: function() { 47 _gAbort = true; 48 } 49 } 50 } 51 59 52 tile.destroy(); 60 53 61 54 t.ok(tile.layer == null, "tile.layer set to null"); … … 64 57 t.ok(tile.position == null, "tile.position set to null"); 65 58 66 59 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."); 67 64 } 68 65 69 66 </script> -
lib/OpenLayers/Tile/WFS.js
old new 28 28 */ 29 29 url: null, 30 30 31 /** 32 * Property: request 33 * {OpenLayers.Ajax.Request} 34 */ 35 request: null, 36 31 37 /** TBD 3.0 - reorder the parameters to the init function to put URL 32 38 * as last, so we can continue to call tile.initialize() 33 39 * without changing the arguments. … … 57 63 this.destroyAllFeatures(); 58 64 this.features = null; 59 65 this.url = null; 66 if (this.request) { 67 this.request.transport.abort(); 68 } 60 69 }, 61 70 62 71 /** … … 97 106 * failure - {function} 98 107 */ 99 108 loadFeaturesForRegion:function(success, failure) { 100 OpenLayers.loadURL(this.url, null, this, success);109 this.request = OpenLayers.loadURL(this.url, null, this, success); 101 110 }, 102 111 103 112 /** -
lib/OpenLayers/Ajax.js
old new 49 49 * onFailure - {Function} callback for failure 50 50 * 51 51 * Both callbacks optional (though silly) 52 * 53 * Returns: 54 * {OpenLayers.Ajax.Request} - Created AJAX request 52 55 */ 53 56 OpenLayers.loadURL = function(uri, params, caller, 54 57 onComplete, onFailure) { … … 64 67 : OpenLayers.nullHandler; 65 68 66 69 // from prototype.js 67 new OpenLayers.Ajax.Request(uri,70 return new OpenLayers.Ajax.Request(uri, 68 71 { method: 'get', 69 72 parameters: params, 70 73 onComplete: success, … … 135 138 */ 136 139 getTransport: function() { 137 140 return OpenLayers.Util.Try( 141 function() {return new XMLHttpRequest();}, 138 142 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');} 141 144 ) || false; 142 145 }, 143 146 … … 167 170 * responderToAdd - {?} 168 171 */ 169 172 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); 176 179 }, 177 180 178 181 /** 182 * Method: unregister 183 * 184 * Parameters: 185 * responderToRemove - {?} 186 */ 187 register: function(responderToRemove) { 188 OpenLayers.Util.removeItem(responderToRemove); 189 }, 190 191 /** 179 192 * Method: dispatch 180 193 * 181 194 * Parameters: 182 195 * callback - {?} 183 196 * request - {?} 184 197 * transport - {?} 185 * json - {?}186 198 */ 187 dispatch: function(callback, request, transport , json) {199 dispatch: function(callback, request, transport) { 188 200 var responder; 189 201 for (var i = 0; i < this.responders.length; i++) { 190 202 responder = this.responders[i]; … … 193 205 typeof responder[callback] == 'function') { 194 206 try { 195 207 responder[callback].apply(responder, 196 [request, transport , json]);208 [request, transport]); 197 209 } catch (e) {} 198 210 } 199 211 } … … 217 229 }); 218 230 219 231 /** 220 * Namespace: OpenLayers.Ajax.Base 221 * {Object} 232 * Class: OpenLayers.Ajax.Base 222 233 */ 223 OpenLayers.Ajax.Base = function() {}; 224 OpenLayers.Ajax.Base.prototype = { 225 234 OpenLayers.Ajax.Base = OpenLayers.Class({ 235 226 236 /** 237 * Constructor: OpenLayers.Ajax 238 * 239 * Parameters: 240 * options - {Object} 241 */ 242 /** 227 243 * Function: setOptions 228 244 * 229 245 * Parameters: 230 246 * options - {Object} 231 247 */ 232 setOptions: function(options) {248 initialize: function(options) { 233 249 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: '' 237 255 }; 238 256 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 } 261 264 } 262 } ;265 }); 263 266 264 265 267 /** 266 268 * Class: OpenLayers.Ajax.Request 267 269 * … … 269 271 * - <OpenLayers.Ajax.Base> 270 272 */ 271 273 OpenLayers.Ajax.Request = OpenLayers.Class(OpenLayers.Ajax.Base, { 274 275 /** 276 * Property: _complete 277 * 278 * {Boolean} 279 */ 280 _complete: false, 272 281 273 /**274 * Constructor: OpenLayers.Ajax.Request275 *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 */ 280 289 initialize: function(url, options) { 290 OpenLayers.Ajax.Base.prototype.initialize.apply(this, [options]); 291 281 292 this.transport = OpenLayers.Ajax.getTransport(); 282 this.setOptions(options);283 293 this.request(url); 284 294 }, 285 295 … … 290 300 * url - {String} 291 301 */ 292 302 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'; 296 311 } 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 } 297 323 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); 301 327 } 302 328 303 329 OpenLayers.Ajax.Responders.dispatch('onCreate', 304 330 this, 305 this.transport);331 response); 306 332 307 this.transport.open(this. options.method,333 this.transport.open(this.method.toUpperCase(), 308 334 this.url, 309 335 this.options.asynchronous); 310 336 311 337 if (this.options.asynchronous) { 312 setTimeout(OpenLayers.Function.bind(313 (function() {this.respondToReadyState(1);}),this), 10314 );338 window.setTimeout( 339 OpenLayers.Function.bind(this.respondToReadyState, this), 340 1000); 315 341 } 316 342 317 343 this.transport.onreadystatechange = 318 344 OpenLayers.Function.bind(this.onStateChange, this); 319 345 this.setRequestHeaders(); 320 346 321 var body = this.options.postBody ? this.options.postBody322 : 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); 324 350 325 351 // Force Firefox to handle ready state 4 for synchronous requests 326 352 if (!this.options.asynchronous && 327 353 this.transport.overrideMimeType) { 328 329 354 this.onStateChange(); 330 355 } 331 332 356 } catch (e) { 333 357 this.dispatchException(e); 334 358 } 335 359 }, 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 }, 336 370 337 371 /** 338 372 * Method: setRequestHeaders 339 373 */ 340 374 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 : ''); 347 384 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'; 357 392 } 358 393 } 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 } 363 407 } 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]); 368 411 } 369 412 }, 370 413 371 414 /** 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 * 384 417 * Returns: 385 * { ?}418 * {Boolean} - 386 419 */ 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); 391 423 }, 392 393 /** 394 * Method: evalJSON395 * 424 425 /** 426 * Method: getStatus 427 * 396 428 * Returns: 397 * { ?}429 * {Integer} - Status 398 430 */ 399 evalJSON: function() {431 getStatus: function() { 400 432 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; 414 434 } catch (e) { 415 this.dispatchException(e);435 return 0 416 436 } 417 437 }, 418 438 … … 423 443 * readyState - {?} 424 444 */ 425 445 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); 428 448 429 if ( event== 'Complete') {449 if (state == 'Complete') { 430 450 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); 437 455 } catch (e) { 438 456 this.dispatchException(e); 439 457 } 440 458 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'); 445 460 } 446 461 447 462 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, 451 466 this, 452 transport, 453 json); 467 response); 454 468 } catch (e) { 455 469 this.dispatchException(e); 456 470 } 457 471 458 // Avoid memory leak in MSIE: clean up the oncomplete event handler459 if (event == 'Complete') {472 if (state == 'Complete') { 473 // avoid memory leak in MSIE: clean up 460 474 this.transport.onreadystatechange = OpenLayers.Ajax.emptyFunction; 461 475 } 462 476 }, 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 }, 463 494 464 495 /** 465 496 * Method: dispatchException … … 468 499 * exception - {?} 469 500 */ 470 501 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); 479 504 OpenLayers.Ajax.Responders.dispatch('onException', this, exception); 480 505 } 481 482 506 }); 483 507 484 508 /** … … 489 513 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; 490 514 491 515 /** 516 * Class: OpenLayers.Ajax.Request 517 * 518 * Inherit: 519 * - <OpenLayers.Ajax.Base> 520 */ 521 OpenLayers.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 /** 492 601 * Function: getElementsByTagNameNS 493 602 * 494 603 * Parameters:
