Is there a way to stop a JavaScript function at any given moment?

I am dealing with a scenario where I have a function that alters some global state, and I need to figure out how to stop this function when a specific condition is met in order to avoid a race condition. Here's an example of the code to make it clearer.

let globalState = 0
const mutateState = () => {
    setTimeout(()=> {
        globalState = Math.random()
    }, Math.random() * 1000);
}
<button onclick="mutateState()"></button>

Essentially, when the user clicks the button, I want to cancel any previous calls to the mutateState function so that the global state remains unchanged.

In addition, it's worth mentioning that I am using Vue.js (although not shown in this example).

Adding conditional statements before each globalState assignment isn't practical due to multiple variables being mutated in my actual code. It becomes cumbersome to add if statements for each one.

My ideal solution would be to completely abort the function.

Answer №1

If you want to stop the callback from executing, you can use clearTimeout(yourTimeoutId):

let currentState = 0
let timeoutId = null;
const changeState = () => {
    timeoutId = setTimeout(()=> {
        currentState = Math.random()
    }, Math.random() * 1000);
}

const cancelChange = () => {
  clearTimeout(timeout);
}

Answer №2

It's difficult to provide a straightforward answer as it largely depends on the specific situation at hand.

One useful tool is the AbortController, which offers a standardized method for halting control flows. While it doesn't possess any automatic magical abilities to terminate processes, APIs can leverage it to determine if a process should be aborted.

For instance, consider its application with fetch:

  controller = new AbortController();
  const signal = controller.signal;
  fetch(url, { signal })

By calling controller.abort();, the fetch operation can be forcibly terminated.

This controller can also find utility within your own code:

let globalState = 0
const mutateState = (() => {
  let abortController;

  return function() {
    abortController?.abort();

    abortController = new AbortController();

    setAbortableTimeout(() => {
        globalState = Math.random();
        
        console.log(abortController.signal.aborted);
        console.log(globalState);
        
      },
      Math.random() * 1000,
      abortController.signal);
  }
})()

function setAbortableTimeout(cb, time, signal) {
  let timer = setTimeout(cb, time);

  signal.addEventListener("abort", () => {
    clearTimeout(timer);
  });

  return timer
}

document.querySelector('button').addEventListener('click', mutateState);
<button>click me</button>

You can monitor signal.aborted or utilize

signal.addEventListener("abort", ...)
to handle the abort event.

The provided code serves as a simplified demonstration of this concept, illustrating how you can implement it in practice.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

.getElementsByTagName function unable to disable dynamically created JavaScript buttons

I am currently attempting to deactivate buttons that have been generated in JavaScript... var upButton = document.createElement('button'); var downButton= document.createElement('button'); var deleteButton = document.createElement(&ap ...

Is there a way in JavaScript to track changes in CSS properties such as transitioning from "display:none" to "display:block"?

Is there a way to detect when the CSS property "display" of an image is changed by another JavaScript script or function and then execute some JS code? I tried using $(this).bind('propertychange', function(){}) but it doesn't work, and setIn ...

What is the best way to bring an image into your nextjs project?

I have a question about importing images into my Next.js project. I created an array of objects and want to import an image stored in a folder on my laptop, specifically in the src folder rather than the public folder. How can I properly achieve this in ...

Is there a way to customize the slicing of *ngFor in a component according to the components it is being injected into?

This code snippet represents a component that needs to be included in other components: <div class="row"> <div class="col-12 [...]" *ngFor="let course of courses"> <div class="card"> ...

Transform a nested JSON array into a JavaScript array

I have a JSON array that looks like this (shortened for simplicity): [ { "name": null, "code": null, "results": [ { "date": "2012-04-28T06:00:00.000Z", "name": null, "value": 135, "unit": "MG/DL", ...

Having trouble identifying the issue with the dependent select drop down in my Active Admin setup (Rails 3.2, Active Admin 1.0)

I am currently working on developing a Ruby on Rails application that involves three models: Games that can be categorized into a Sector (referred to as GameSector) and a subsector (known as GameSubsector) A sector consists of multiple subsectors. A Subs ...

How to bind data to an already data-bound element in Vue 2

To view a JS Fiddle example of this concept, click the link below: JS Fiddle Demo Essentially, I have three text areas. The content entered in the first text area should automatically appear in the second text area, which will then be copied to the third ...

The search function for selecting plugins is not functioning properly when additional options are added

Is there a way to use select options with search functionality, but the options are appended? I've tried using plugins like tom-select, selectize, and chosen but none of them seem to work with the appended options. Can anyone provide assistance on how ...

What is the best way to render multiple Flatlists using a map function in React Native?

I am facing a puzzling issue that I can't quite grasp. My goal is to exhibit messages stored in an array using multiple flatlists and then categorize them by date. These messages are essentially a series of chat conversations containing questions an ...

Adding a new key-value pair to a JSON data structure

Here is the JSON object that I am currently handling: { "name": "John Smith", "age": 32, "employed": true, "address": { "street": "701 First Ave.", "city": "Sunnyvale, CA 95125", "country": "United States" }, ...

Distinguish the components of a standard union in TypeScript

I am looking to incorporate the following feature: const foo = <S>(newState: S | ((prevState: S) => S)) => {...} This function should accept either a new state of type S, or a function that generates the new state from the old state. In my i ...

Ajax request missing Github Basic OAuth token in authentication process

My personal access token is not being passed to the request when I make an ajax call. I keep receiving an error message saying API rate limit exceeded for 94.143.188.0. (But here's the good news: Authenticated requests get a higher rate limit.. I atte ...

Utilize the 'on send success' action hook to trigger dual actions in Contact Form 7 within WordPress

Is it possible to utilize the on sent ok action hook for two different purposes? I want to both track the email address and redirect the user to a thank you page. My attempts to do this in the 'Additional Settings' section of the Contact Form 7 p ...

What is the best way to ensure that these buttons adapt seamlessly to various screen

How do I adjust the size of buttons in my HTML and CSS elements based on screen size? Currently, when I resize the window, the buttons disappear instead of resizing to fit into a column layout. Here is my CSS code snippet: /* grid */ .col-1of1 { width: ...

What is preventing me from obtaining the select and input values?

I'm currently facing an issue where I am unable to retrieve the values of customInput and customSelect and store them in the state. The challenge arises when trying to integrate these components into a react dashboard material-ui setup. Strangely, whe ...

Ways to automatically scroll the page to the top when new content is loaded on a Single Page Application

I've recently integrated the Single Page Application Plugin in my website built with octoberCMS and also included smooth-scrollbar.js. While most things are working smoothly, there's one issue I'm facing - smooth-scrollbar doesn't auto ...

Arranging items in Angular based on selection from the database

i have data in table: Id, word, score , score_list. score are 0.4, 0.2, -0.5, 0, -0.3 .... in score_list i have positive, negative , neutral. How can i sort data with select by score_list? This is html <select class="form-control"> <option> ...

Click on the header to activate the accordion link with a trigger

I am having an issue with a trigger. My goal is to make the accordions collapse not only by clicking on the link, but also by clicking on the entire header panel. Below is my header's code: <div class="accordion-head" role="tab"> <div cl ...

Understanding AJAX Code

Recently, I've been experimenting with Jquery AJAX for a few days and stumbled upon this code snippet online: While I understand the general functionality of the code, there are certain parts that remain unclear to me. For instance, I'm unsure ...

What is the best way to pass a variable from PHP to JavaScript?

How can I pass a variable value from PHP to Javascript using Ajax? Take a look at the JS code and PHP code below: PHP CODE: <?php $username = "trainerapp"; $password = "password"; $hostname = "localhost"; $link = @mysql_connect($hostna ...