1

I would like to call a function in NodeJS which checks Date.Now continuously if a flag is set to true.

I cannot use setInterval because it is too inaccurate.

My function works fine, but I want to call the function without blocking the whole code, so I thought an async method would do the job, but it isn't:

var bufferLogRunning = true;
var dn_counter;
var masterbuffer_cache_log = [];

async function f() {
  let promise = new Promise((resolve, reject) => {
    console.log('FUNCION CALLED')
    var start = Date.now();
    while (bufferLogRunning == true) {
      if (dn_counter != Date.now() - start && dn_counter != undefined) {
        masterbuffer_cache_log.push({
          "millis": dn_counter,
          "buffer": "masterbuffer_cache"
        })
      }
      dn_counter = Date.now() - start
      if (Date.now() - start >= 4000) {
        bufferLogRunning = false;
      }
    }
    console.log('DONE')
    resolve("done!")
  });
  let result = await promise;
}

console.log('FIRST')
f();
console.log('SECOND')

How do I execute console.log('SECOND') while f() is running in background?

1
  • I cannot use setInterval because it is too inaccurate. even if you use an interval that is smaller than the interval you actually want to use? Commented Mar 25, 2021 at 11:11

2 Answers 2

1

An async function does not magically convert code into something that does not block. It is just syntactic sugar to work with Promises.

What you can do is to use setImmediate

Schedules the "immediate" execution of the callback after I/O events' callbacks.

And wrap that into a Promise:

function pause() {
   return new Promise((resolve, reject) => {
      setImmediate(resolve)
   })
}

and call that function in your while loop, and use await to interrupt the execution of your while loop until the promise returned by pause resolves.

And using new Promise((resolve, reject) in your code does not make any sense

var bufferLogRunning = true;
var dn_counter;
var masterbuffer_cache_log = [];

async function f() {

  console.log('FUNCION CALLED')
  var start = Date.now();
  while (bufferLogRunning == true) {

    await pause(); // interrupt the execution to let I/O events happen 

    if (dn_counter != Date.now() - start && dn_counter != undefined) {
      masterbuffer_cache_log.push({
        "millis": dn_counter,
        "buffer": "masterbuffer_cache"
      })
    }
    
    dn_counter = Date.now() - start
    if (Date.now() - start >= 4000) {
      bufferLogRunning = false;
    }
  }
  console.log('DONE')

  let result = "done!"
}

console.log('FIRST')
f();
console.log('SECOND')

If setImmediate won't work in your use-case, you could replace it withsetTimeout.

Sign up to request clarification or add additional context in comments.

1 Comment

That worked like charm! Thank you very much and I appreciate the explanation.
1

This is the code from my program, with inline comments. Please have a look

// Your app
const APP = {
  //
  // Cycle
  //
  cycle: (cb, timeout = 1e3, times = false) => {
    const start = Date.now();
    let i = 0;
    // Set delay method
    const delay = ms => {
      i++;
      // Check if stop enabled, then return immediately
      if(delay.stopTrigger || times && i > times) return true;
      // Run function
      const now = Date.now();
      const diff = now - start - i * timeout;
      // Run callback
      cb(now);
      // Set new timeout
      setTimeout(() => {
        // Compensate diff
        // We will compensate delay to
        // make it more accurate 
        delay(timeout-diff);
      }, ms);
    };
    // Set stop method
    delay.stopTrigger = false;
    delay.stop = () => delay.stopTrigger = true;
    // Run cycle with timeout
    setTimeout(delay, timeout, timeout);
    // Return delay object
    return delay;
  },
  
  //
  // Sync timeout function
  //
  timeout: ms => new Promise(resolve => setTimeout(resolve, ms)),
  
  //
  // !!!
  //
  // Your logic
  //
  init: async () => {
    // Start some cycle task for 500ms
    // First param is your function,
    // Second (optional/1000ms) - the delay amount in ms,
    // Third (optional/infinite) - cycles number
    const task = APP.cycle(now => {
      // Lets print something in a loop
      console.log(`Cycle task ${now}`);
    }, 500);
    
    // Now task holds stop method so we
    // can stop our cycle from this scope
    // But for now lets do some sync work
    
    // Sleep for 3 sec
    await APP.timeout(3000);
    
    // Print something
    console.log(`Hello from caller!`);
    
    // Sleep for 3 sec
    await APP.timeout(3000);
    
    // Print something and stop cycle
    console.log(`Hello from caller again and stop cycle now!`);
    task.stop();
    
    // Sleep for 3 sec
    await APP.timeout(3000);
    
     // Print something at the end
    console.log(`Hello from caller! All work done, exit now ;)`);
  }
};

// Run app
APP.init();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.