createTaskProcessorWorker.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import defaultValue from "../Core/defaultValue.js";
  2. import defined from "../Core/defined.js";
  3. import formatError from "../Core/formatError.js";
  4. // createXXXGeometry functions may return Geometry or a Promise that resolves to Geometry
  5. // if the function requires access to ApproximateTerrainHeights.
  6. // For fully synchronous functions, just wrapping the function call in a Promise doesn't
  7. // handle errors correctly, hence try-catch
  8. function callAndWrap(workerFunction, parameters, transferableObjects) {
  9. let resultOrPromise;
  10. try {
  11. resultOrPromise = workerFunction(parameters, transferableObjects);
  12. return resultOrPromise; // errors handled by Promise
  13. } catch (e) {
  14. return Promise.reject(e);
  15. }
  16. }
  17. /**
  18. * Creates an adapter function to allow a calculation function to operate as a Web Worker,
  19. * paired with TaskProcessor, to receive tasks and return results.
  20. *
  21. * @function createTaskProcessorWorker
  22. *
  23. * @param {createTaskProcessorWorker.WorkerFunction} workerFunction The calculation function,
  24. * which takes parameters and returns a result.
  25. * @returns {createTaskProcessorWorker.TaskProcessorWorkerFunction} A function that adapts the
  26. * calculation function to work as a Web Worker onmessage listener with TaskProcessor.
  27. *
  28. *
  29. * @example
  30. * function doCalculation(parameters, transferableObjects) {
  31. * // calculate some result using the inputs in parameters
  32. * return result;
  33. * }
  34. *
  35. * return Cesium.createTaskProcessorWorker(doCalculation);
  36. * // the resulting function is compatible with TaskProcessor
  37. *
  38. * @see TaskProcessor
  39. * @see {@link http://www.w3.org/TR/workers/|Web Workers}
  40. * @see {@link http://www.w3.org/TR/html5/common-dom-interfaces.html#transferable-objects|Transferable objects}
  41. */
  42. function createTaskProcessorWorker(workerFunction) {
  43. let postMessage;
  44. return function (event) {
  45. const data = event.data;
  46. const transferableObjects = [];
  47. const responseMessage = {
  48. id: data.id,
  49. result: undefined,
  50. error: undefined,
  51. };
  52. return Promise.resolve(
  53. callAndWrap(workerFunction, data.parameters, transferableObjects)
  54. )
  55. .then(function (result) {
  56. responseMessage.result = result;
  57. })
  58. .catch(function (e) {
  59. if (e instanceof Error) {
  60. // Errors can't be posted in a message, copy the properties
  61. responseMessage.error = {
  62. name: e.name,
  63. message: e.message,
  64. stack: e.stack,
  65. };
  66. } else {
  67. responseMessage.error = e;
  68. }
  69. })
  70. .finally(function () {
  71. if (!defined(postMessage)) {
  72. postMessage = defaultValue(self.webkitPostMessage, self.postMessage);
  73. }
  74. if (!data.canTransferArrayBuffer) {
  75. transferableObjects.length = 0;
  76. }
  77. try {
  78. postMessage(responseMessage, transferableObjects);
  79. } catch (e) {
  80. // something went wrong trying to post the message, post a simpler
  81. // error that we can be sure will be cloneable
  82. responseMessage.result = undefined;
  83. responseMessage.error = `postMessage failed with error: ${formatError(
  84. e
  85. )}\n with responseMessage: ${JSON.stringify(responseMessage)}`;
  86. postMessage(responseMessage);
  87. }
  88. });
  89. };
  90. }
  91. /**
  92. * A function that performs a calculation in a Web Worker.
  93. * @callback createTaskProcessorWorker.WorkerFunction
  94. *
  95. * @param {Object} parameters Parameters to the calculation.
  96. * @param {Array} transferableObjects An array that should be filled with references to objects inside
  97. * the result that should be transferred back to the main document instead of copied.
  98. * @returns {Object} The result of the calculation.
  99. *
  100. * @example
  101. * function calculate(parameters, transferableObjects) {
  102. * // perform whatever calculation is necessary.
  103. * const typedArray = new Float32Array(0);
  104. *
  105. * // typed arrays are transferable
  106. * transferableObjects.push(typedArray)
  107. *
  108. * return {
  109. * typedArray : typedArray
  110. * };
  111. * }
  112. */
  113. /**
  114. * A Web Worker message event handler function that handles the interaction with TaskProcessor,
  115. * specifically, task ID management and posting a response message containing the result.
  116. * @callback createTaskProcessorWorker.TaskProcessorWorkerFunction
  117. *
  118. * @param {Object} event The onmessage event object.
  119. */
  120. export default createTaskProcessorWorker;