Vue.js Human Time Component Overwhelms CPU Usage

This specific component is designed to convert a timestamp into relative time text:

Vue.component('human-time', {
  props: ['time'],
  methods: {
    format(time){ 
      const formats = [
        [60, 'seconds', 1],
        [120, '1 minute'],
        [3600, 'minutes', 60],
        [7200, '1 hour'],
        [86400, 'hours', 3600],
        [172800, '1 day'],
        [604800, 'days', 86400],
        [1209600, '1 week'],
        [2419200, 'weeks', 604800],
        [4838400, '1 month'],
        [29030400, 'months', 2419200],
        [58060800, '1 year'],
        [2903040000, 'years', 29030400]
      ];

      time = +new Date(time);

      let s = (+new Date() - time) / 1000;
      if(s === 0)
        return 'Just now';

      if(s < 0)
        s = Math.abs(s);

      for(const[limit, text, one] of formats)
        if(s < limit)
          return one ? Math.floor(s / one) + ' ' + text : text;

      return time;    
    }

  },

  render(createElement){

    // update human time every second
    this.intv = setInterval(() => this.$el.textContent = this.format(this.time), 1000);

    const localTime = (new Date(this.time)).toString();
    return createElement('time', { attrs : { datetime: this.time, title: localTime }}, this.format(this.time));
  },

  beforeDestroy(){
    clearInterval(this.intv);
  }

});

To use this component, simply include it like this:

<human-time :time="entry.time"></human-time>

The issue arises when there are numerous entries (500+) causing excessive CPU usage in Chrome. This could be due to Chrome struggling with a large number of timers. Do you have any recommendations on how to address this problem while maintaining the real-time updates for relative time?

Answer №1

Here are a few key enhancements:

  1. Shift the setInterval function from render() to mounted() to prevent multiple calls during updates and avoid unnecessary creation of intervals. Refer to Vue: Life cycle diagram for more details.

  2. Introduce a data property to store the current formatted time, eliminating the need for manual manipulation of DOM text content using this.$el.textContent.

  3. Implement a watch to synchronize the latest props=time with the data property=current

Note: I've included a console.log statement in render() so that you can observe why placing setInterval within render() is highly inefficient and leads to high CPU usage.

Vue.component('human-time', {
  props: ['time'],
  methods: {
    format(time){ 
      const formats = [
        [60, 'seconds', 1],
        [120, '1 minute'],
        [3600, 'minutes', 60],
        [7200, '1 hour'],
        [86400, 'hours', 3600],
        [172800, '1 day'],
        [604800, 'days', 86400],
        [1209600, '1 week'],
        [2419200, 'weeks', 604800],
        [4838400, '1 month'],
        [29030400, 'months', 2419200],
        [58060800, '1 year'],
        [2903040000, 'years', 29030400]
      ];

      time = +new Date(time);

      let s = (+new Date() - time) / 1000;
      if(s === 0)
        return 'Just now';

      if(s < 0)
        s = Math.abs(s);

      for(const[limit, text, one] of formats)
        if(s < limit)
          return one ? Math.floor(s / one) + ' ' + text : text;

      return time;    
    }

  },
  data () {
    return {
      current: this.format(this.time)
    }
  },
  watch: {
    time: function (newVal) {
      this.current = this.format(newVal)
    }
  },
  mounted () {
    this.intv = setInterval(() => this.current = this.format(this.time), 1000);
  },
  render(createElement){

    // update human time every second
    
    console.log('ex: rendering')
    const localTime = (new Date(this.time)).toString();
    return createElement('span', { attrs : { datetime: this.time, title: localTime }}, this.current);
  },

  beforeDestroy(){
    clearInterval(this.intv);
  }

})

new Vue ({
  el:'#app'
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
    <div class="container">
        <human-time :time="new Date()"></human-time>
        <human-time :time="new Date() - 120000"></human-time>
    </div>
</div>

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

Tips on concealing a div until the value of a specific field surpasses zero

In order to ensure that users focus on the first section of the form before proceeding, I plan to hide the last section until a specific field has a value greater than zero. Check out my HTML code below: <div class="fieldcontainer"> <label>E- ...

Animate the tubular geometric pathway by continuously updating its values

When creating a TubeGeometry, I supplied a SplineCurve3 / CatmullRomCurve3 path as a parameter. My goal is to update the position of each point on the path using geometry.parameters.path.points[1].y += 0.01; within the requestAnimationFrame loop. Even tho ...

Creating reusable components in Vue.js can enhance code reusability and make development

I am new to Vue.js and WebUI development, so I apologize in advance if I make any mistakes. Currently, I am exploring how to create reusable components using Vue.js. Specifically, I am working on a treeview component with the ability to customize the rend ...

React JS onClick() failing intermittently

I've spent hours trying to solve this problem. The issue first arose on iOS while working on a website I had recently launched. I've tested the code below, and it works correctly 90% of the time, but occasionally fails. <button className=" ...

What is the best way to trigger b-tab based on a specific condition?

Hey there, I'm just starting out with Vue3 and I have a bit of a challenge. I've got an SVG image with different parts, a data variable that changes when a particular part of the image is clicked, and some tabs (b-tabs). Is it possible to automat ...

Issues with rendering in-line styles in ReactJS after a state update

I'm currently working on implementing a basic state change for a button in React. 'use strict'; class ReactButton extends React.Component { constructor(props) { super(props); this.state = {hovering: false}; } onClick() { ...

Adding a Vue.js component within another component

I recently created a dashboard.vue component and tried to import the table.vue component into it. However, I ran into an issue where the table.vue component wasn't showing up on my webpage or in the vue.dev tools. Interestingly, when I imported the t ...

Generating JSON using Node.js

Currently, I am working on pushing names to a JSON file. The code snippet I have tried is: socket.on('create json', function(data){ var data = JSON.stringify(Data, null, 2); fs.writeFile('participants.json', data) console.l ...

Is there a way to transfer the input value from a textfield in one component to another component in ReactJS?

I have a scenario where I need to pass the value of a text area from one component in reactjs to another. The component's value is stored using a useState hook in the first component, and I want to access it in another component to run a map() functio ...

Having trouble with installing Angular JS on my computer

On my machine, I have successfully installed node.js version v0.12.0. However, when attempting to run sudo npm install, I encountered the following errors: npm ERR! install Couldn't read dependencies npm ERR! Darwin 14.0.0 npm ERR! argv "node" "/usr/ ...

Ways to use string functions in JavaScript to substitute with /

Here is the image path I am working with: var str = "D:\Poc\testProject\DataPush\public\unzip\cust\AccountData\2.jpg" When I included "unzip" in the path, it threw an error as shown in this image, but when ...

Are you planning to print the JSON information?

I've been working on mastering JavaScript and decided to create a script that displays all public Facebook statuses related to a specific keyword. However, things aren't going as planned. You can find a sample URL where the JSON data is located h ...

Guide on updating a form by utilizing the [profile.js] file in React.js

I'm currently working on an admin panel using Reactjs with the Nextjs Framework. My task involves updating user profiles, so I created a file called "profile.js" where I pass the userId to fetch user information and update the form when the user click ...

display a div positioned relatively next to another div

I'm having trouble displaying a textbox next to another div on my webpage. Instead of appearing next to the div, it is showing up below it. The textbox needs to have an absolute position. You can see the issue in action by checking out this demo. Than ...

Changing the website address | Node.js | Express

Is there a way to redirect incoming requests to different endpoints depending on a query parameter in the request? For instance, http://localhost:9000/?category=xyz&param1=...&param2=... The category value can be any of [abc, ijk, pqr, xyz]. Gi ...

I'm trying to figure out how to make HTML tags display within a React/Next <head> element

I inherited a React/Next project filled with spaghetti code. The previous developer did not prioritize SEO, and I am still learning React. Now, my main focus is getting tags to render in the Component. <Head> <meta key="data-tes ...

Does the round function always produce the most accurate floating point approximation?

Will the result of using round(3.12143345454353,2) always be equivalent to simply using the literal value 3.12? The floating point approximation would suggest so (3.12000000000000010658141036401502788066864013671875). In simpler terms, can we rely on the ...

Formatting a phone number using v-model in VueJs

Is there a way to automatically format phone numbers entered into the input field as (123) - 456 - 78 - 90? <template> <div v-for="about in abouts"> <input type="text" v-model="about.phone"> <input t ...

Extract keys from the string

Is there a better way to extract keys from a string? const {Builder, By, Key, until} = require('selenium-webdriver'); ... const obj = {val: 'Key.SPACE'} if(obj.val.startsWith('Key.'))obj.val = eval(obj.val); (...).sendKeys(obj ...

Binding Events to Elements within an AngularJS-powered User Interface using a LoopIterator

I am working with an Array of Objects in AngularJS that includes: EmployeeComments ManagerComments ParticipantsComments. [{ "id": "1", "title": "Question1", "ManagerComment": "This was a Job Wel Done", "EmployeeComment": "Wow I am Surprised", ...