Note for those who use JS timer in their pages 📢 This bug might be there for you guys too!
Tags: javascript, frontend, typescript, vue
Published: 2023-10-05 03:52:27

## Background and Issues
In the project, certain pages need to poll for requests to update the page, using setInterval.

However, we found that the polling doesn't stop after leaving the page (component), **and it is occasional, but it recurs when I click the page in and then quickly switch out**. My first instinct was that the timer was not cleared when I left the page (component). But after reviewing the code, I realized that there is a timer cleanup, similar to the following code:

```js
  mounted() {
    // Perform other logic
    this.timer = setInterval(() => {
      console.log("I'm refreshing");
    }, 5000);
  }, 
  unmounted() {
    clearInterval(this.timer);
  },
```

So what could be the problem? Upon closer inspection, **there is some other logic before starting the timer, such as requesting an interface and needing to wait for a return before starting the timer**. The approximate logic is as follows:

```diff
  async mounted() {
    // Perform other logic
+   // Execute a request
+   await new Promise((resolve) => {
+    setTimeout(() => resolve(), 1000)
+   });
+   console.log('First implementation');
    this.timer = setInterval(() => {
      console.log("I'm refreshing");
    }, 1000);
  },
  unmounted() {
    clearInterval(this.timer);
  },
```

Sample code can be seen here, [sample code 1](https://codesandbox.io/s/quirky-darwin-xswjlc?file=/src/components/Demo1.vue).

So the problem here is that **before the timer is enabled, we have already left this page (component), and after we have left the page (component), the code in the memory only turns on the timer **.

For better understanding, you can see the following flow:


![Normal process vs. exception process](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/08e52d8eml9tygib8fn0.png)



### How to solve

### Method 1: Start the timer immediately
Since this is caused by a late start of the timer, it might be an idea to start it right when you enter the page (component). However, there are obvious drawbacks to this approach, which may not necessarily fulfill the business requirements. Because the logic inside the timer is likely to rely on the front of some time-consuming operations (such as requesting the data obtained). So this is not recommended.

### Method 2: Leaving the page (component) via a logo
This method is also very simple, it is to define an identifier, such as isLeavePage, which is initialized to false and set to true when leaving the page (component), then we can judge it in the logic of the timer, and if it is true, then we can clear the timer directly. The following is a simple example code:

```diff
  async mounted() {
    // Perform other logic
    // Execute a request
    await new Promise((resolve) => {
      setTimeout(() => resolve(), 1000);
    });
    console.log("First implementation");
    this.timer = setInterval(() => {
+      if (this.isLeavePage && this.timer) {
+       clearInterval(this.timer);
+       return;
+     }
      console.log("I'm refreshing");
    }, 1000);
  },
  unmounted() {
+    this.isLeavePage = true;
    clearInterval(this.timer);
  },
```

The downside is that there is some code intrusiveness, but as you can see, the amount of code is still relatively small.

### Method 3: Not using timers
This kind of is to avoid the problem from the root, such as the polling scenario, you can use similar WebSockets / Server-Sent Events and other technologies instead. We won't expand on this here.

### Possible approach 4: How to leave the page (component) without executing in-memory code execution?
The above question is essentially the same as the question of code execution in memory after leaving the page (component). If we can destroy the page (component) and then no longer execute the code in memory, wouldn't that be a good idea? Unfortunately, I don't see any way to do this in JS.

## Summary
Timer, we often use in the project, and see online examples are also in the page (component) to clear the timer can be left.

But in fact, it may be because of the front operation logic is more time-consuming, resulting in the user to leave the page (component) before turning on the timer, which may result in a less-than-expected page.

In this article, we share several solution ideas, I hope they are helpful to you, if you have other ideas, you are also welcome to discuss them!