Webworkers

File: webworkers.html (click for a live demo)

<!DOCTYPE html>
<html>
<head>
  <title>math.js | web workers</title>
</head>
<body>

<p>
  In this example, a math.js parser is running in a separate
  <a href="http://www.html5rocks.com/en/tutorials/workers/basics/">web worker</a>,
  preventing the user interface from freezing during heavy calculations.
</p>

<p id="results"></p>

<script>
  /**
   * MathWorker evaluates expressions asynchronously in a web worker.
   *
   * Example usage:
   *
   *     const worker = new MathWorker()
   *     const expr = '12 / (2.3 + 0.7)'
   *     worker.eval(expr, function (err, result) {
   *       console.log(err, result)
   *     })
   */
  function MathWorker () {
    this.worker = new Worker('worker.js')
    this.callbacks = {}
    this.seq = 0

    // create a listener to receive responses from the web worker
    const me = this
    this.worker.addEventListener('message', function(event) {
      const response = JSON.parse(event.data)

      // find the callback corresponding to this response
      const callback = me.callbacks[response.id]
      delete me.callbacks[response.id]

      // call the requests callback with the result
      callback(response.err, response.result)
    }, false)
  }

  /**
   * Evaluate an expression
   * @param {string} expr
   * @param {Function} callback   Called as callback(err, result)
   */
  MathWorker.prototype.eval = function eval (expr, callback) {
    // build a request,
    // add an id so we can link returned responses to the right callback
    const id = this.seq++
    const request = {
      id: id,
      expr: expr
    }

    // queue the callback, it will be called when the worker returns the result
    this.callbacks[id] = callback

    // send the request to the worker
    this.worker.postMessage(JSON.stringify(request))
  }

  // create a MathWorker
  const worker = new MathWorker()

  // evaluate an expression via the worker
  worker.eval('12 / (2.3 + 0.7)', function (err, result) {
    document.getElementById('results').innerHTML += 'result: ' + result + '<br>'
  })

</script>

</body>
</html>

File: worker.js (click for a live demo)

importScripts('https://unpkg.com/mathjs@5.1.2/dist/math.min.js')

// create a parser
const parser = self.math.parser()

self.addEventListener('message', function (event) {
  const request = JSON.parse(event.data)
  let result = null
  let err = null

  try {
    // evaluate the expression
    result = parser.eval(request.expr)
  } catch (e) {
    // return the error
    err = e
  }

  // build a response
  const response = {
    id: request.id,
    result: result,
    err: err
  }

  // send the response back
  self.postMessage(JSON.stringify(response))
}, false)

Fork me on GitHub