0

How to stop or reset the execution of a function?

I tried to add a value with the start number to the "while(true)" and return if the number of the launched eval does not match "if (RUN != 39629) return;", but it seems to me that this does not always work correctly. I would like to somehow reliably stop the execution of a running eval.

let a = 0;
let code = `while(true){ 
await sleep(1000);
cons('step:'+a);
a++;
}`;

$('span').click(e => {
    if ($(e.target).text() == 'start') {
  cons('start'); 
  eval("(async () => {" + code + "})()");
  }
});

function sleep(ms) {
    return new Promise((resolve) => {
        setTimeout(resolve, ms);
    });
}

function cons(s)
{
    $('div').html($('div').html()+ s +'<br>');
}
span { cursor: pointer; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span>start</span> <span>stop</span>
<div>...<br></div>
  • If you don't control the code, you can't stop it from running. Your best bet might be a web worker which you can kill from outside. – Bergi Jan 16 '22 at 15:07
  • "*I tried to add a value with the start number to the "while(true)" and return if the number of the launched eval does not match*" - that sounds like a good approach. Please show us the exact code you tried and explain how it did "*not always work correctly*". – Bergi Jan 16 '22 at 15:09
  • Ok, I've added an answer below with a code with a return variable: https://stackoverflow.com/a/70732367/12680601 – iNji 555 Jan 16 '22 at 17:19

2 Answers2

0

The following works to stop the execution of the loop and restart it. It's using a separate done variable to check in the loop.

However, note that this only works because sleep is using setTimeout during which the handlers from jQuery can be triggered. Without that it wouldn't work as JS is single-threaded, see this question. The stop handler would not be called and the loop run forever.

let done = false;
let a = 0;
let code = `while(!done){ 
await sleep(1000);
cons('step:'+a);
a++;
}`;

$('span').click(e => {
    const target = $(e.target).text()
    if (target === 'start') {
        done = false
        a = 0
        cons('start'); 
        eval("(async () => {" + code + "})()");
    }
    if (target === 'stop') {
        done = true
    }
});

function sleep(ms) {
    return new Promise((resolve) => {
        setTimeout(resolve, ms);
    });
}

function cons(s)
{
    $('div').html($('div').html()+ s +'<br>');
}
span { cursor: pointer; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span>start</span> <span>stop</span>
<div>...<br></div>
matthiasgiger
  • 1,086
  • 9
  • 17
0

Added at the request to show an example with a return variable and what is wrong with it. In order for it to work correctly, it must be inserted into each line of code in order to be able to interrupt the execution of eval at really any time, otherwise part of the code is still executed after clicking on the stop.

start stop
...
start
step:0
next:0
step:1
next:1
step:2
stop <-!!!!!
next:2 <-!!!!!

let a = 0;
let run = 0;
let code = `while(true){ 
if (run != 100) return;
cons('step:'+a);
await sleep(5000);
cons('next:'+a);
a++;
}`;

$('span').click(e => {
    if ($(e.target).text() == 'start') {
    run = 100;
  cons('start'); 
  eval("(async () => {" + code + "})()");
  }
  if ($(e.target).text() == 'stop') {
    run = 0;
    cons('stop');
  }
});

function sleep(ms) {
    return new Promise((resolve) => {
        setTimeout(resolve, ms);
    });
}

function cons(s)
{
    $('div').html($('div').html()+ s +'<br>');
}
span { cursor: pointer; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span>start</span> <span>stop</span>
<div>...<br></div>