throttleRequestByServer.js 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /*global define*/
  2. define([], function() {
  3. "use strict";
  4. var Uri = Cesium.Uri;
  5. var when = Cesium.when;
  6. var defaultValue = Cesium.defaultValue;
  7. var activeRequests = {};
  8. var pageUri = typeof document !== 'undefined' ? new Uri(document.location.href) : new Uri();
  9. function getServer(url) {
  10. var uri = new Uri(url).resolve(pageUri);
  11. uri.normalize();
  12. var server = uri.authority;
  13. if (!/:/.test(server)) {
  14. server = server + ':' + (uri.scheme === 'https' ? '443' : '80');
  15. }
  16. return server;
  17. }
  18. /**
  19. * Because browsers throttle the number of parallel requests allowed to each server,
  20. * this function tracks the number of active requests in progress to each server, and
  21. * returns undefined immediately if the request would exceed the maximum, allowing
  22. * the caller to retry later, instead of queueing indefinitely under the browser's control.
  23. *
  24. * @exports throttleRequestByServer
  25. *
  26. * @param {String} url The URL to request.
  27. * @param {throttleRequestByServer~RequestFunction} requestFunction The actual function that
  28. * makes the request.
  29. * @returns {Promise.<Object>|undefined} Either undefined, meaning the request would exceed the maximum number of
  30. * parallel requests, or a Promise for the requested data.
  31. *
  32. *
  33. * @example
  34. * // throttle requests for an image
  35. * var url = 'http://madeupserver.example.com/myImage.png';
  36. * function requestFunction(url) {
  37. * // in this simple example, loadImage could be used directly as requestFunction.
  38. * return Cesium.loadImage(url);
  39. * };
  40. * var promise = Cesium.throttleRequestByServer(url, requestFunction);
  41. * if (!Cesium.defined(promise)) {
  42. * // too many active requests in progress, try again later.
  43. * } else {
  44. * promise.then(function(image) {
  45. * // handle loaded image
  46. * });
  47. * }
  48. *
  49. * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
  50. */
  51. function throttleRequestByServer(url, requestFunction) {
  52. var server = getServer(url);
  53. var activeRequestsForServer = defaultValue(activeRequests[server], 0);
  54. if (activeRequestsForServer >= throttleRequestByServer.maximumRequestsPerServer) {
  55. return undefined;
  56. }
  57. activeRequests[server] = activeRequestsForServer + 1;
  58. return when(requestFunction(url), function(result) {
  59. activeRequests[server]--;
  60. return result;
  61. }).otherwise(function(error) {
  62. activeRequests[server]--;
  63. return when.reject(error);
  64. });
  65. }
  66. /**
  67. * Specifies the maximum number of requests that can be simultaneously open to a single server. If this value is higher than
  68. * the number of requests per server actually allowed by the web browser, Cesium's ability to prioritize requests will be adversely
  69. * affected.
  70. * @type {Number}
  71. * @default 6
  72. */
  73. throttleRequestByServer.maximumRequestsPerServer = 6;
  74. /**
  75. * A function that will make a request if there are available slots to the server.
  76. * @callback throttleRequestByServer~RequestFunction
  77. *
  78. * @param {String} url The url to request.
  79. * @returns {Promise.<Object>} A promise for the requested data.
  80. */
  81. return throttleRequestByServer;
  82. });