Search code examples
javascriptfunctionexit

How to stop custom function in JavaScript


look at this code

const code = "..." // can be anything, it is unknown 
const func = new Function(code)

// run `func` and ignore possible errors in code
function run() {
  try { func() } finally {}
}

// stop `func` execution
function stop() {
  ???
}

$runButton.onclick = run
$stopButton.onclick = stop

Is there any way to stop function execution

I just need to rerun function multiple times, kind of playground

But if code has timers, or infinite loops it freezes behaves badly

I don't want to reload playground site every time

Any ideas?

Same Situation in TS Playground, they don't care (press run multiple times)

Tried this, but that does not make sense If that function's body is unpredictable

Also another way, which seems to be the most inefficient

Put checks in every line of function's body, and if flag is false break main label which is declared at the top of function's body for 'return' effect

let isRunning = true

code.split('/n').map(line => ';' + `if (!isRunning) break functionLabel` + ';' + line)

const functionBody = `functionLabel: { ${code} }`

const func = new Function(functionBody)

Solution

  • Create a web worker and pass code as message, theoretically, it should run it in the background not affecting the main thread. Then terminate worker if you need to stop execution

    For multiple 'reruns' reinit worker

    worker.js

    self.addEventListener('message', event => {
      const { code  } = event.data
      const func = new Function(code)
      try {
        func()
        self.postMessage('code ran successfully')
      } catch (error) {
        // handle possible error
        self.postMessage('code ran with errors')
      }
    })
    
    

    main.js

    let worker = null
    
    function run() {
      let code = '...'
      worker?.postMessage({ code  })
    }
    
    function stop() {
      if (worker == null) {
        worker = new Worker(pathToWorker)
        worker.addEventListener('message', event => {
          console.log(event.data)
        })
      } else {
        worker.terminate()
        worker = null
      }
    }
    

    Web Workers Support (98%)