Pause console output using Node.js - javascript

I am trying to create a time display (h:mm:ss) with just using the console and not on a web page. The time should be set initially and from there display the time as it changes.
When using the output console (in the web browser) or in vscode, is it possible for js or node.js, while printing thousands/multiple outputs to have a delay between each output being printed in the console without using an extension?

Here's an example of printing the current time to the console every 1 second:
// setInterval() executes the given function on a given time interval
setInterval(() => {
console.log(new Date().toTimeString()); // function to execute
}, 1000) // execute every 1000 ms
You can also print your own counter:
let secondsElapsed = 0
setInterval(() => {
console.log(`seconds elapsed = ${secondsElapsed}`);
secondsElapsed++;
}, 1000)

Here is how to accomplish what you seem to be asking:
const clockTick = (callback) => {
const tick = () => {
const now = Date.now();
callback(now);
setTimeout(tick, 1000 - (now % 1000));
}
tick();
}
clockTick(timestamp => {
const date = new Date(timestamp);
const hours = date.getHours();
const minutes = date.getMinutes();
const seconds = date.getSeconds();
console.log(`${hours}:${minutes}:${seconds}`);
});

The accepted answer isn't correct. IMO, we should implement a queue or something similar in order to achieve "delay between each output". I find this question interesting so I implement this code for some fun (which use promise chain as a simple queue):
const callNext = (function () {
let queueChain = Promise.resolve();
// Called after previous command (1 second by default)
function callNext(func, delay = 1000) {
queueChain = queueChain.then(() => {
return new Promise((res) => {
setTimeout(() => {
func();
res();
}, delay);
});
});
}
return callNext;
})();
callNext(() => {
console.log('run after 3s')
}, 3000);
callNext(() => {
console.log('run after the above 3s')
}, 3000);
callNext(() => {
console.log('run after the above 1s by default')
});
we can create a simple logger using the above callNext for cleaner syntax:
const logger = (function () {
function createLogFn(name) {
return function (...args) {
let delay = 1000;
// take the last argument as "delay" param
if (typeof args[args.length -1] === 'number') {
delay = args.pop();
}
callNext(() => {
console[name](`${name.toUpperCase()} [${(new Date().toISOString())}]: `, ...args);
}, delay);
};
}
const logger = {
log: createLogFn('log'),
info: createLogFn('info'),
debug: createLogFn('debug'),
error: createLogFn('error'),
}
return logger;
})();
logger.log('run after 3s', 3000);
logger.log('run after the above 3s', 3000);
logger.log('run after the above 1s');
logger.info('final run after the above 2s', 2000);
Check it out: https://jsfiddle.net/pk5oqfxa/

Related

Sort of await setInterval

I need to re-execute a hand made for loop (because I need time between each step) 10s after it ends forever.
So after few tries, I came with this code, but it doesn't work because it re-executes every 10s, not after the loop finishes. I tried to but async function in the interval and put all my code in an await one, but it didn't work.
async function refreshEDT() {
let rows = appModel.getAll()
let orderFiliere = {};
await rows.then((res) => {
for (let i = 0; i < res.length; i++) {
if (res[i].filiere in orderFiliere) {
orderFiliere[res[i].filiere].push(res[i])
} else {
orderFiliere[res[i].filiere] = [res[i]]
}
}
})
return orderFiliere
}
let edt = refreshEDT()
setInterval(() => {
edt = refreshEDT()
}, 1000 * 60 * 60) //ms to s to m to h
setInterval(() => {
edt.then((lessons) => {
(function loop(i) {
let lessons_key = Object.keys(lessons)
setTimeout(() => {
// processing things
if (--i) loop(i);
}, 1000 * 10) //ms to s to 10s
})(Object.keys(lessons).length - 1)
})
console.log(1)
}, 1000 * 10) //ms to s to 10s
Do you have any solution?
Ty!
EDIT
Let's explain what I try to do:
I get things on my DB, try to classify by "filiere", one of my column, and return that object.
Those data are reloaded every hour.
After that, I need to emit with socket.io every "filiere" with 10s between, and repeat that.
Perhaps the code will be easier to read when you wrap setTimeout with a promise to await.
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function refreshEDT() {
const res = await appModel.getAll();
const orderFiliere = res.reduce((acc, value) => {
const { filiere } = value;
if (filiere in acc) {
acc[filiere].push(value);
} else {
acc[filiere] = [value];
}
return acc;
}, {});
return orderFiliere;
}
// consider naming this
(async () => {
let edt = refreshEDT();
setInterval(() => {
edt = refreshEDT();
}, 1000 * 60 * 60);
while (true) {
const lessons = await edt;
for (const lessons_key of Object.keys(lessons)) {
await sleep(1000 * 10);
// processing things
}
// repeat after 10 seconds
await sleep(1000 * 10);
}
})();
With ES2022, you can use Array.prototype.groupBy() to simplify your refreshEDT() implementation:
async function refreshEDT() {
const res = await appModel.getAll();
const orderFiliere = res.groupBy(({ filiere }) => filiere);
return orderFiliere;
}
You could try using setTimeout to call your function again.
const myFunc = () => {
// processing things
setTimeout(myFunc , 10000)
}
myFunc();
I think this could help if i understood the problem correctly :
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async yourFunction() {
const secondsToWait: number = 10;
let i = 0;
for (let item of List) {
// Do stuff
if (i === list.length -1) {
await wait(secondsToWait*1000);
yourFunction();
}
i++;
}
}

Decorators in javascript

function debounce(f, ms) {
let isCool = false;
return function() {
if (!isCool) {
f.apply(this, arguments);
}
isCool = true;
setTimeout(() => isCool = false, ms);
};
}
let f = debounce(alert, 1000);
f(1); // runs immediately
f(2); // ignored
setTimeout(() => f(3), 100); // ignored ( only 100 ms passed )
setTimeout(() => f(4), 1100); // runs
setTimeout(() => f(5), 1500); // ignored (less than 1000 ms from the last run)
The result of debounce(f, ms) decorator should be a wrapper that passes the call to f at maximum once per ms milliseconds. When we call a “debounced” function, it guarantees that all future calls to the function made less than ms milliseconds after the previous call will be ignored.
Why my code doesn't working as it should be? It should ignore call to f(5), instead it runs...
#deceze's comment answers your question. I'll add that there's no reason to complicate matters with setTimeout. Simply track time between invocations.
function debounce(f, ms) {
let lastApply = 0;
const cooldownMs = ms;
return function() {
let now = Date.now();
if ((now - cooldownMs) >= lastApply) {
lastApply = now;
f.apply(this, arguments);
}
};
}
let f = debounce(console.log, 1000);
f(1); // runs immediately
f(2); // ignored
setTimeout(() => f(3), 100); // ignored ( only 100 ms passed )
setTimeout(() => f(4), 1100); // runs
setTimeout(() => f(5), 1500); // ignored (less than 1000 ms from the last run)

How to measure the execution time of an asynchronous function in nodejs?

I'm trying to get the execution/response time of an asynchronous function that executes inside a node-fetch operation, like the following
async function getEditedData() {
var a = await fetch(`https://api.example.com/resorce_example`);
var b = await a.json();
// Some aditional treatment of the object obtained (b)
console.log("End of the asynchronous function")
}
I Used the library perf_hooks like this, but the execution time shows before
const hrtime = require ('perf_hooks').performance.now ;
var start = hrtime ();
getEditedData();
var end = hrtime ();
console.log (end - start);
I found the async_hooks library https://nodejs.org/api/perf_hooks.html#perf_hooks_measuring_the_duration_of_async_operations , but I can´t understand how it works. I am a basic in javascript/nodejs
You could simply store Date.now() in some variable and then check Date.now() when your Promise resolves (or rejects) and subtract to find the difference. For example:
const simulateSomeAsyncFunction = new Promise((resolve, reject) => {
console.log('Initiating some async process, please wait...')
const startTime = Date.now();
setTimeout(() => {
resolve(Date.now() - startTime);
}, 3000);
});
simulateSomeAsyncFunction.then(msElapsed => {
console.log(`Async function took ${msElapsed / 1000} seconds to complete.`);
});
Note: You could write code that achieves the same thing and appears to be synchronous by using await/async since that is just "syntactic sugar" built on top of Promises. For example:
const simulateSomeAsyncFunction = () => {
console.log('Initiating some async process, please wait...');
return new Promise((resolve, reject) => {
setTimeout(resolve, 3000);
});
};
// Await is required to be called within an async function so we have to wrap the calling code in an async IIFE
(async() => {
const startTime = Date.now();
await simulateSomeAsyncFunction();
const msElapsed = Date.now() - startTime;
console.log(`Async function took ${msElapsed / 1000} seconds to complete.`);
})();
Starting with a simple async function -
const fakeAsync = async (value) => {
const delay = 2000 + Math.random() * 3000 // 2 - 5 seconds
return new Promise(r => setTimeout(r, delay, value))
}
fakeAsync("foo").then(console.log)
console.log("please wait...")
// "please wait..."
// "foo"
We could write a generic function, timeit. This is a higher-order function that accepts a function as input and returns a new function as output. The new function operates like a decorated version of the original -
const timeit = (func = identity) => async (...args) => {
const t = Date.now()
const result = await func(...args)
return { duration: Date.now() - t, result }
}
// decorate the original
const timedFakeAsync = timeit(fakeAsync)
// call the decorated function
timedFakeAsync("hello").then(console.log)
timedFakeAsync("earth").then(console.log)
// { duration: 3614, result: "earth" }
// { duration: 4757, result: "hello" }
The timed version of our function returns an object, { duration, result }, that reports the runtime of our async function and the result.
Expand the snippet below to verify the results in your own browser -
const identity = x =>
x
const timeit = (func = identity) => async (...args) => {
const t = Date.now()
const result = await func(...args)
return { duration: Date.now() - t, result }
}
const fakeAsync = async (value) => {
const delay = 2000 + Math.random() * 3000 // 2 - 5 seconds
return new Promise(r => setTimeout(r, delay, value))
}
const timedFakeAsync = timeit(fakeAsync)
timedFakeAsync("hello").then(console.log)
timedFakeAsync("earth").then(console.log)
console.log("please wait...")
// "please wait..."
// { duration: 3614, result: "earth" }
// { duration: 4757, result: "hello" }
If you expect to set the end after getEditedData() is completed, you actually need to await getEditedData(). Otherwise, you'll go right past it while it executes... asynchrnously.

Expected valuable after setTimeout in which is set

I cannot set for expected valuable to equal in setTimeout.
I have two valuable is:
const first = 0;
const second = 0;
but that throw error is Uncauth TypeError: You provided 'undefined' where a stream was expected. You can provider an Observable, Promise, Array, or Interable.
setNumber() {
setTimeout(() => {
first = 12;
second = 1235
}, 250);
it('Should execute setNumber', fakeAsync(() => {`
setTimeout(() => {
expected(first).toEqual(12);
expected(second ).toEqual(1235);
}, 251)
}))
In fakeAsync function use tick() for emulate timeout. Something just like this:
it('Should execute setNumber', fakeAsync(() => {
let first;
let second;
setTimeout(() => {
first = 12;
second = 1235;
}, 250);
tick(251);
expect(first).toEqual(12);
expect(second).toEqual(1235);
}));
For understanding, tick with 249 and test will be failed.
it('Should execute setNumber', fakeAsync(() => {
let first;
let second;
setTimeout(() => {
first = 12;
second = 1235;
}, 250);
tick(249);
expect(first).toEqual(12);
expect(second).toEqual(1235);
}));
Hope I helped you :)

How to write a function "inOrder" that accepts two callbacks and invokes them in order.

How to Implement "inOrder" using the callback pattern and using Promises.
var logOne = setTimeout(function() {
console.log("one!");
}, Math.random() * 1000);
var logTwo = setTimeout(function() {
console.log("two!");
}, Math.random() * 1000);
inOrder(logOne, logTwo);
// one
// two
// it should always log those two in order regardless of their timing
Its impossible with setTimeout directly as you cant do delays etc. But you could create a wrapper that provides a few more options:
function timer(cb, ms) {
let start = +new Date;
let timeout = setTimeout(cb, ms);
return {
ms,
stop() {
if(!timeout) return;
clearTimeout(timeout);
ms -= (start - new Date);
timeout = null;
},
start() {
if(ms > 0 && !timeout) {
start = +new Date;
timeout = setTimeout(cb, ms);
}
},
delay(time) {
this.stop();
ms += time;
this.start();
}
};
}
So now it is quite easy:
function inOrder(a, b) {
if(a.ms > b.ms)
b.delay(a.ms - b.ms);
}
Usable as:
const one = timer(() => console.log("one"), 1000);
const two = timer(() => console.log("two"), 500);
inOrder(one, two);
Create two function logOne & logTwo and can resolve them using Promise.resolve
function logOne() {
setTimeout(function() {
console.log("one!");
}, Math.random() * 1000);
}
function logTwo() {
setTimeout(function() {
console.log("two!");
}, Math.random() * 5000);
}
function inOrder(a, b) {
Promise.resolve(a()).then(b())
}
inOrder(logOne, logTwo);
A friend of mine has asked me to help him with this one.
So first thing is you won't make it work unless you can use nodejs. In nodejs setTimeout returns Timer object, which (with a little hacky code) you can use to make it work.
Inside browser it's impossible without creating some kind of a wrapper around those functions. #Jonas Wilms has already showed it, so let me show you my hacky implementation:
var logOne = setTimeout(function () {
console.log('one!');
}, 5000);
var logTwo = setTimeout(function () {
console.log('two!');
}, 0);
function inOrder(logOne, logTwo) {
var logTwoCallback = logTwo._onTimeout;
clearTimeout(logTwo);
setTimeout(function checkTimeout() {
if (logOne._called) {
logTwoCallback();
} else {
setTimeout(checkTimeout, 0);
}
}, 0);
}
inOrder(logOne, logTwo);

Categories