Run function after 2 sec delay in nodejs - node.js

This is a simple node js hander in cloud function that is getting called . It is calling another function redisApiCacheRemove as below . I want to call this function after 2 sec of delay , can do it . Something like , wait for 2 sec and then run that function redisApiCacheRemove
exports.drm = (request, response) => {
const pubsubmessage = Buffer.from(request.body.message.data, 'base64').toString();
console.log('message received >>' + pubsubmessage);
const pubsubMessage = JSON.parse(pubsubmessage);
console.log(pubsubMessage.entity.id);
redisApiCacheRemove(pubsubMessage.entity.id, pubsubMessage.entity.event);
return response.status(200).send();
;

You just need to use setTimeout like this
const delay = 2000 // In milliseconds
setTimeout(() => {
// The code you want to execute after 2 seconds goes here
}, delay)
setTimeout also returns timeoutID that you can use to clear the timeout if you want to cancel the timeout before it happens, e.g
const delay = 2000 // In milliseconds
const timeoutID = setTimeout(() => {
// The code you want to execute after 2 seconds goes here
}, delay)
clearTimeout(timeoutID) // Will cancel the timeout above

Related

setTimeout gets overwritten by second setTimeout in Node.js

const express = require("express");
const REFRESH_INTERVAL = 1000;
const app = express();
const recurringSetTimeout = (id) => {
setTimeout(
handle = async () => {
console.log(`Starting setTimeout${id}`);
setTimeout(handle, REFRESH_INTERVAL);
},
REFRESH_INTERVAL,
)
}
const main = () => {
app.get("/t1", async (req, res) => {
const msg = "Starting timeout 1...";
console.log(msg)
recurringSetTimeout(1);
res.send(msg);
});
app.get("/t2", async (req, res) => {
const msg = "Starting timeout 2...";
console.log(msg)
recurringSetTimeout(2);
res.send(msg);
});
app.listen(3000, () => {
console.log("Server is running...");
});
}
main();
I have this code that should run two different setTimeouts on two route calls, t1 runs first and t2 runs second. After calling t1 I am getting correct results in logs, "Starting setTimeout1" and after each second again. But when I call t2, I am expecting to get "Starting setTimeout2" but as well as "Starting setTimeout1" from the previous route call. But it seems that setTimeout2 somehow overrides setTimeout1, since I am getting only "Starting setTimeout2" but after each second two logs, instead of one. So it seems that setTimeout1 is running but gets overwritten by setTimeout2, since I am getting only timeout2 logs (2 per second).
If I run setInterval, instead of setTimeout, it works fine, but I want to understand this behaviour of setTimeout, can someone please explain. Thanks!

Google cloud functions - setInterval function quits after 15 mins

My app uses a Firebase function that is triggered when my Firebase realtime database is modified.
The function initiates a setInterval function that is supposed to loop for an hour then terminate....HOWEVER it seems to quit after 15mins.
Im guessing this is a restriction put in place by Firebase...does anyone know how I can get around this?See code below
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
//this gets triggered when db is updated
exports.onActiveUpdate = functions.database
.ref('/pathToRealtimeDb').onUpdate(() => {
let counter = setInterval(() => {
//count down from 60 mins to zero then exit
}, 60000); //end setInterval
});

Call a async function every minute for 5 minutes in nodejs

I am trying to call a async function every minute for 5 minutes before exiting the main function. Below is the print_data() function which I am calling in main() function.
var print_data = async () => {
console.log("Hello")
}
async function main() {
process.stderr.write("--Start--")
var data = await print_data()
console.log(data)
}
main()
Very new to writing async function. What is the best way to call print_data function every minute for 5 minutes and print the output each minute? I tried something using setInterval and was not able to execute the function completely.
Any help would be good. Thank you in advance.
This is one way to do it using setInterval and clearInterval. Read more about it here: https://nodejs.org/api/timers.html#timers_clearinterval_timeout
Using IIFE to prevent polluting of the global scope.
(function (){
let counter = 0; //counter to keep track of number of times the setInterval Cb is called
let data; // to store reference of Timeout object as returned by setInterval, this is used in clearInterval
const print_data = async () => {
console.log("Hello")
counter++;
if (counter == '5') {
clearInterval(data);
}
}
async function main() {
process.stderr.write("--Start--")
data = setInterval(print_data, 1000*60); //60 seconds
}
main();
})();
Please check if the below code can be a solution.
var print_data = async () => {
console.log("Hello")
return "Hello";
}
var call_print_data = () => new Promise((resolve, reject) => {
var count = 0;
var interval = setInterval(async () => {
var res = await print_data();
count += 1;
if (count === 5) { // if it has been run 5 times, we resolve the promise
clearInterval(interval);
resolve(res); // result of promise
}
}, 1000 * 60); // 1 min interval
});
async function main() {
process.stderr.write("--Start--")
var data = await call_print_data(); // The main function will wait 5 minutes here
console.log(data)
}
main()

Pushing query result from back end to front end with interval

I'm playing around with sockets for the first time and have a created a very simple back end and front end to test with our system at work.
I want the back end to query our server every 10 seconds in this example and pass the results to the front end.
I currently have the interval set as 10 seconds however when I run it I only get the result after ten seconds - i want the result straight away and then to check every ten seconds for changes.
I've tried moving code around and seeing what works, but I usually get a message telling me the variable is undefined (because it is then obviously outside the function.
My code is below - I am aware its probably a it overkill having the set interval in both the result and catch, so if anyone can help tidy it up so it works correctly, I'd appreciate it. Still a bit of a noob I'm afraid!
const express = require("express");
const app = express();
const server = require("http").createServer(app);
const io = require("socket.io")(server);
const oledb = require('oledb');
const smartconn =
`--myodbcconnection--`;
const db = oledb.odbcConnection(smartconn);
let command = `SELECT item FROM mytable.table LIMIT 10`
db.query(command)
.then(result => {
setInterval(function(){
io.emit("query", result.result);
}, 10000);
},
err => {
setInterval(function(){
io.emit("query", err);
}, 10000);
});
io.set("origins", "*:*");
io.on("connection", async (socket) => {
console.log("Client Successfully Connected");
});
server.listen(5000, () => {
console.log("Backend Server is running on http://localhost:5000");
});
Expect results to show immediately. Previously the old method didn't use sockets and polled the using set interval from the front end, which I want to move away from.
Here's one way to do it:
//Resolves a Promise after ms milliseconds
const sleep = (ms) => {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms);
});
}
//Returns a db.query result with server status
const getServerStatus = async () => {
return await db.query(`SELECT item FROM mytable.table LIMIT 10`);
}
//Runs indefinitely and emits events to frontend every 10 seconds
(async () => {
while(true){
try{
const result = await getServerStatus();
io.emit("query", result.result);
} catch (error){
io.emit("query", error); //It would be better to change the event name to something else
}
await sleep(10000);
}
})();
This way the first event will be sent immediately because unlike setInterval, my implementation waits after executing the code, not before. Also, you can be sure that queries will not overlap when they take more than 10s to execute. setInterval doesn't guarantee that the next execution will wait for the previous one to finish.
The downside is that events will be sent after (10,000ms + query_delay), so depending on your database size and performance, some of them might get delayed by a few or a few hundred milliseconds. To counter that, you can measure getServerStatus's execution time and subtract it from the wait time.
Sorted it, by moving the emit functions into the io.on function.
Cheers!

Add intentional latency in express

Im using express with node.js, and testing certain routes. I'm doing this tute at http://coenraets.org/blog/2012/10/creating-a-rest-api-using-node-js-express-and-mongodb/
Im calling the http://localhost:3000/wines via ajax (the content doesn't matter). But I want to test latency. Can I do something like make express respond after 2 seconds? (I want to simulate the ajax loader and I'm running on localhost so my latency is pretty much nil)
Use as middleware, for all your requests
app.use(function(req,res,next){setTimeout(next,1000)});
Just call res.send inside of a setTimeout:
setTimeout((() => {
res.send(items)
}), 2000)
To apply it globaly on all requests you can use the following code:
app.use( ( req, res, next ) => {
setTimeout(next, Math.floor( ( Math.random() * 2000 ) + 100 ) );
});
Time values are:
Max = 2000 (sort of.... min value is added so in reality its 2100)
Min = 100
Try connect-pause module. It adds delay to all or only some routes in your app.
app.get('/fakeDelay', function(req,res){
let ms = req.query.t;
ms = (ms>5000 || isNaN(ms)) ? 1000 : parseInt(ms);
setTimeout((()=> res.status(200).send({delay:ms})), ms);
})
Then request the URL as: http://localhost/fakeDelay/?t=2000
(max 5000ms and default of 1000ms on this example)
Update:
Using a Promise. The function 'sleep' can be used for delaying any Express response or other async function.
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
app.get('/fakeDelay', async (req, res) => {
await sleep(500);
res.send([])
})
just add a comment on top of the solution of #maggocnx : put this middleware early (before your route handler)
app.use(function(req,res,next){setTimeout(next,1000)});
You could also just write your own generic delay handler using a Promise or callback (using a q promise in this case):
pause.js:
var q = require('q');
function pause(time) {
var deferred = q.defer();
// if the supplied time value is not a number,
// set it to 0,
// else use supplied value
time = isNaN(time) ? 0 : time;
// Logging that this function has been called,
// just in case you forgot about a pause() you added somewhere,
// and you think your code is just running super-slow :)
console.log('pause()-ing for ' + time + ' milliseconds');
setTimeout(function () {
deferred.resolve();
}, time);
return deferred.promise;
}
module.exports = pause;
then use it however you'd like:
server.js:
var pause = require('./pause');
router.get('/items', function (req, res) {
var items = [];
pause(2000)
.then(function () {
res.send(items)
});
});
You can use the express-delay package.
The code below will delay all incoming requests by one second.
const app = require('express')();
const delay = require('express-delay');
app.use(delay(1000));
The package also offers the possibility to introduce a random delay within specified boundaries, e.g. by calling delay(1000, 2000) for a delay between one and two seconds.
In my case I wanted a way to have the same processing time for all of my endpoints.
The solution I found is to override one of the Response methods :
/* MINIMUM DELAY */
const minDelay = 200; /* ms */
app.use((req, res, next) => {
const tmp = res.json;
const start = new Date().getTime();
(res.json as any) = async (body: any) => {
await new Promise((re) => setTimeout(re, minDelay - new Date().getTime() + start));
tmp.apply(res, [body]);
};
next();
});
This way an attacker would not be able to differentiate failed login requests from OK requests just by looking at the response time :)

Resources