# How can I make code run after a certain time? Without blocking the rest

**URL:** https://discourse.nodered.org/t/how-can-i-make-code-run-after-a-certain-time-without-blocking-the-rest/86836
**Category:** Developing Nodes
**Created:** [28 March 2024 15:58 UTC](https://discourse.nodered.org/t/how-can-i-make-code-run-after-a-certain-time-without-blocking-the-rest/86836 "2024-03-28T15:58:44Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![hansimeister](https://avatars.discourse-cdn.com/v4/letter/h/a88e4f/32.png) [@hansimeister](https://discourse.nodered.org/u/hansimeister)
#### Post date: [28 March 2024 15:58 UTC](https://discourse.nodered.org/t/how-can-i-make-code-run-after-a-certain-time-without-blocking-the-rest/86836/1 "2024-03-28T15:58:44Z")

</div>

Hi there! I have the code below. It runs smoothly however the token expires after 1hr and I have to fetch a new one, create a new connection, new session etc. How can I do this 1hr after first obtaining the token? All my attempts with setTimout/setInterval have failed due to e.g. the endpoint becoming unavailable. TY

```auto
const fetch = require('node-fetch');
const WebSocket = require('ws');
let myconfig = {};

module.exports = function myNode(RED) {
  myconfig.RED = RED;
  // RED.nodes.registerType('sivideo-server', SiVideoServer, {});

  // ... any setup functions here...

  RED.nodes.registerType('sivideo-server', SiVideoServer);
};

// this is run once for each node instance of the node in flows
function SiVideoServer(config) {
  if (!myconfig.RED) {
    console.log('RED not set');
    return;
  }
  const RED = myconfig.RED;

  // Initialize "this"
  RED.nodes.createNode(this, config);
  const node = this;
  this.allEvents = [];
  this.host = config.host;
  this.username = config.username;
  this.password = config.password;
  this.getToken = getToken;
  this.registerListener = registerListener;
  this.deRegisterListener = deRegisterListener;
  const Listeners = {};

  console.log('Listeners at start:', Listeners);
  // Get the bearer token for websocket authentication
  if (this.host && this.username && this.password) {
     connectWithNewToken();

  } else {
    console.log('No host, username, or password provided');
  }
    
  function connectWithNewToken() {
    getToken(node.host, node.username, node.password)
      .then((token) => {
        node.context().set('token', token);
        if (token) {
          // Close the existing WebSocket connection if it exists
          if (node.ws) {
            node.ws.removeAllListeners();
            node.ws.close();
          }

          // Create a new WebSocket connection
          node.ws = new WebSocket(`ws://${node.host}/api/ws/events/v1`, {
            headers: {
              Authorization: `Bearer ${token}`,
            },
          });

          console.log('Websocket connection created');
          startSession(node);
          listenForAllEvents(node);

          // Listen for message events
          node.ws.on('message', (data) => {
            for (const [id, cb] of Object.entries(Listeners)) {
              console.log('Sending data to listener:', id);
              cb(data);
            }
          });
        } else {
          console.log('No token obtained');
        }
      })
      .catch((error) => {
        console.error('Error fetching token:', error);
        setTimeout(connectWithNewToken, 5000); // Reconnect after 5 seconds
      });
  }
  // Define a new endpoint to get the event types from the Milestone server
  RED.httpAdmin.get('/getEventTypes', function (req, res) {
    console.log('Get event types is running');
    // serverNode = RED.nodes.getNode(config.server); - not necessary
    const token = node.context().get('token');
    if (token) {
      const options = {
        method: 'GET',
        headers: {
          Authorization: `Bearer ${token}`,
        },
      };
      fetch(`http://${config.host}/API/rest/v1/eventTypes`, options)
        .then((response) => {
          if (!response.ok) {
            throw new Error('Error fetching event types');
          }
          return response.json();
        })
        .then((data) => {
          const result = data.array.map((item) => ({
            value: item.id,
            label: item.displayName,
          }));
          result.sort((a, b) => a.label.localeCompare(b.label));
          // add all EventTypes
          result.unshift({ value: 'all-events', label: 'All Events' });
          node.allEvents = result;
          res.status(200).send(result);
        })
        .catch((error) => {
          console.error('Error fetching event types:', error);
          res.status(500).send('Error fetching event types');
        });
    }
  });

  // Register and deregister listeners
  function registerListener(NodeID, Callback) {
    // start own session so that every node has its own session
    console.log('Registering listener:', NodeID);
    Listeners[NodeID] = Callback;
    console.log('Current Listeners:', Listeners);
  }

  function deRegisterListener(NodeID) {
    console.log('De-registering listener:', NodeID);
    delete Listeners[NodeID];
  }
}

// get the token from the server
async function getToken(host, username, password) {
  try {
    const formData = new URLSearchParams();
    formData.append('grant_type', 'password');
    formData.append('client_id', 'GrantValidatorClient');
    formData.append('username', username);
    formData.append('password', password);
    const response = await fetch(`http://${host}/idp/connect/token`, {
      method: 'POST',
      headers: {
        'Content-type': 'application/x-www-form-urlencoded',
      },
      body: formData,
    });

    if (response.ok) {
      const data = await response.json();
      // console.log('Token:', data.access_token);
      return data.access_token;
    } else {
      console.error('HTTP Error:', response.status);
      return null;
    }
  } catch (error) {
    console.error('Error fetching token:', error);
    throw error;
  }
}

function startSession(server) {
  // Start a session
  server.ws.on('open', () =>
    server.ws.send(
      JSON.stringify({
        command: 'startSession',
        commandId: 1,
        sessionId: '',
        eventId: '',
      }),
    ),
  );
  console.log('Session started');
}

function listenForAllEvents(server) {
  server.ws.on('open', () =>
    server.ws.send(
      JSON.stringify({
        command: 'addSubscription',
        commandId: 1,
        filters: [
          {
            modifier: 'include',
            resourceTypes: ['*'],
            sourceIds: ['*'],
            eventTypes: ['*'],
          },
        ],
      }),
    ),
  );
  console.log('Server listener for all Events added');
}

```

---

<div class="post-metadata">

### Author: ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)
#### Post date: [28 March 2024 16:38 UTC](https://discourse.nodered.org/t/how-can-i-make-code-run-after-a-certain-time-without-blocking-the-rest/86836/2 "2024-03-28T16:38:45Z")

</div>

Off the top of my head and with no testing:

Add a statement at the start of `connectWithNewToken` to destroy the websocket connection (which should also destroy the event listener I think?) if it exists.

That means you can safely re-run that function.

Now set up a timer - `setInterval()` - that re-runs the function about every 55 minutes or so.

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)
#### Post date: [27 May 2024 16:39 UTC](https://discourse.nodered.org/t/how-can-i-make-code-run-after-a-certain-time-without-blocking-the-rest/86836/3 "2024-05-27T16:39:27Z")

</div>

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.
