I want to shutdown my computer 1 min after I push button, and if I push button again it will shutdown after it push last time.
for(var i=1; i<=10; ++i){
setDelay();
}
var nn;
function setDelay(){
clearTimeout(nn);
nn = setTimeout(function(){
console.log("shutdown");
}, 60000);
}
But my code have another "setTimeout" too. Will it work fine ?, or will it damage my other setTimeout ?
I'd suggest you create an object that allows you to add time to it:
function Timer(t, fn) {
this.fn = fn;
this.time = Date.now() + t;
this.updateTimer();
}
Timer.prototype.addTime = function(t) {
this.time += t;
this.updateTimer();
}
Timer.prototype.stop = function() {
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
}
Timer.prototype.updateTimer = function() {
var self = this;
this.stop();
var delta = this.time - Date.now();
if (delta > 0) {
this.timer = setTimeout(function() {
self.timer = null;
self.fn();
}, delta);
}
}
Then, you can use it like this:
var timer = new Timer(60000, function() {
console.log("shutdown");
});
// add one second of time
timer.addTime(1000);
// add one minute of time
timer.addTime(1000 * 60);
Related
I am updating database fields by using setTimeout(). So when the updates are multiple what happens is the the last primary key is used for all the updates. How do I run the setTimeout() function sequentially. Below is the portion of code which does that.
for( var i = 0; i < req.body.devicelist.length; i++) { //running for loop for multiple elements
var data = JSONPARSE.toObject(req.body);
mac_id = req.body.devicelist[i];
data.mac_id = mac_id;
var gateway_config;
for (let j = 0; j < gateways_config.length; j++) { //code for fetching specific element. IGNORE
if(gateways_config[j].latest_config.mac_id == mac_id){
gateway_config = gateways_config[j]
break;
}
gateway_config = undefined
}
await syncConfig(req.body,gateway_config, req.decoded.id);
..........
..........
}
syncConfig(body,gateway,user_id){
var jsonObj = body;
...
...
...
config_timeout_array[jsonObj.mac_id] = setTimeout(() => { //Causing problem
commandTimeout(jsonObj.org_id,jsonObj.mac_id)
}, 10000);
...
...
}
commandTimeout:(org_id, mac_id) =>{
console.log(mac_id); //prints same mac_id (the last in the array)
return gateway_model.findOneAndUpdate({ org_id: org_id, mac_id: mac_id }, { 'sync_sent': false }, {"new": true})
.then((updated_gateway) => {
...
...
...
}
}
config_timeout_array[jsonObj.mac_id] = setTimeout(() => { //Causing problem
commandTimeout(jsonObj.org_id,jsonObj.mac_id)
}, 10000);
Instead of doing the above logic directly, call a function and do it there. I don't know why but it worked!
seqTimeout(jsonObj.org_id,jsonObj.mac_id); //function call
seqTimeout(org_id,mac_id){
config_timeout_array[mac_id] = setTimeout(() => {
GatewayController.commandTimeout(org_id, mac_id);
}, COMMAND_TIMEOUT);
}
I'm trying to alter the interval by using a the variable 'counter'.
The Twitter stream is working and the LED is blinking.
I have removed all the twitter credentials.
Any help would be greatly appreciated!
Here is my code:
var Gpio = require('onoff').Gpio;
var Twit = require('twit');
var T = new Twit({
consumer_key: '' // Your Consumer Key
, consumer_secret: '' // Your Co$
, access_token: '' // Your Ac$
, access_token_secret: '' // Your Access $
});
var stream = T.stream('statuses/filter', { track: '#blessed, #peace'})
led = new Gpio(17, 'out'),
counter = 500;
stream.start();
var iv = setInterval(function(){
led.writeSync(led.readSync() === 0 ? 1 : 0);
}, counter);
stream.on('tweet', function(tweet) {
if(tweet.text.indexOf('#blessed') > -1) {
console.log("blessed");
counter += 100;
} else if (tweet.text.indexOf('#peace') > -1) {
console.log("peace");
counter -= 100;
}
});
Once you've made the setInterval() call, the timer's locked in, you can't change it. This is how arguments to functions work: Changing them after the fact does nothing. There is no binding to the value supplied, numbers get passed in as a copy.
You'll need to clear and re-set the timer. setInterval() returns a handle you can pass through to clearInterval() to turn it off. You've captured this, so you just need to use it:
var iv;
function blink(interval) {
if (iv) {
clearInterval(iv);
}
iv = setInterval(function() {
led.writeSync(led.readSync() === 0 ? 1 : 0);
}, interval);
}
Then use this function to reset it:
counter -= 100;
blink(counter);
Just make sure you don't go negative.
I added a check to counter and interval:
var Gpio = require('onoff').Gpio;
var Twit = require('twit');
var T = new Twit({
consumer_key: '' // Your Consumer Key
, consumer_secret: '' // Your Co$
, access_token: '' // Your Ac$
, access_token_secret: '' // Your Access $
});
var stream = T.stream('statuses/filter', { track: '#blessed, #peace'})
led = new Gpio(17, 'out'),
counter = 200;
stream.start();
var iv;
function blink(interval) {
if (iv) {
clearInterval(iv);
}
if (interval <= 100) {
interval = 100;
}
console.log("interval = " + interval);
iv = setInterval(function(){
led.writeSync(led.readSync() === 0 ? 1 : 0);
}, interval);
}
stream.on('tweet', function(tweet) {
if(tweet.text.indexOf('#blessed') > -1) {
console.log("blessed");
counter += 100;
if (counter <= 100) {
counter = 100;
}
console.log(counter);
blink(counter);
} else if (tweet.text.indexOf('#peace') > -1) {
console.log("peace");
counter -= 100;
if (counter <= 100) {
counter = 100;
}
console.log(counter);
blink(counter);
}
});
How would you go about applying a time limit to a series of callbacks in node.js?
Would this be easier using the async library?
Thankyou, as you can see I'm struggling with asynchronous javascript.
Instead of calling the next step directly, call the below function with
doNext : your actual next step
stepData : your parameters plus an execution time limit in miliseconds
unDoThis : the function to run if the work just done ever must be undone
function nextStep(doNext, stepData, unDoThis) {
The first time, set the time out
if (!stepData.expireAt) {
var currentDate = new Date();
stepData.expireAt = currentDate.setMilliseconds(currentDate.getMilliseconds() + stepData.runMiliseconds);
console.log(new Date().toISOString() +" We will expire at "
+ new Date(stepData.expireAt).toISOString());
};
Remember how to undo the last completed step
if (!stepData.unDoAll) stepData.unDoAll = [];
if (unDoThis) stepData.unDoAll.push(unDoThis);
If time is expired, undo all completed steps
if (new Date(stepData.expireAt) < new Date().getTime()) {
while (stepData.unDoAll.length) {
var unDoOne = stepData.unDoAll.pop();
unDoOne();
}
console.log(new Date().toISOString() +' That was it!');
else perform the next step
} else {
doNext(stepData, Array.prototype.slice.call(arguments, 2));
}
}
From the below worker functions we will build the chain that we will interupt
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
function oneStep(stepData) {
console.log (new Date().toISOString() +' ('+ stepData.nrIterations +') I do some stuff ');
sleep(100);
var myIteration = stepData.nrIterations--;
if (stepData.nrIterations) {
nextStep(otherStep, stepData);
}
}
function otherStep(stepData) {
console.log (new Date().toISOString() +' ('+ stepData.nrIterations +') I do more stuff, leaving a trace');
sleep(100);
var myIteration = stepData.nrIterations--;
if (stepData.nrIterations) {
nextStep(oneStep, stepData, function () {
console.log(new Date().toISOString() +' ('+ myIteration +') I clean some trace ');
});
}
}
And now we use it.
Play around with runMiliseconds and nrIterations to see the effect
console.log (new Date().toISOString() + ' About to start ');
var currentDate = new Date();
nextStep(oneStep, {
runMiliseconds : 250,
nrIterations: 22
});
jsfiddle link: http://jsfiddle.net/T8ee7/
When I call Knockout's subscribe method is there a way I can get both the previous and new value? Right now, I can only call get these values separately.
I want to trigger some code if the old and new value are different.
I suppose I could do the following, but it can get messy...
(http://jsfiddle.net/MV3fN/)
var sv = sv || {};
sv.PagedRequest = function (pageNumber, pageSize) {
this.pageNumber = ko.observable(pageNumber || 1);
this.numberOfPages = ko.observable(1);
this.pageSize = ko.observable(pageSize || sv.DefaultPageSize);
};
var _pagedRequest = new sv.PagedRequest();
var oldValue;
_pagedRequest.pageNumber.subscribe(function (previousValue) {
console.log("old: " + previousValue);
oldValue = previousValue;
}, _pagedRequest, "beforeChange");
_pagedRequest.pageNumber.subscribe(function (newValue) {
console.log("new: " + newValue);
if (oldValue != newValue) {
console.log("value changed!");
}
});
_pagedRequest.pageNumber(10);
_pagedRequest.pageNumber(20);
I prefer using an observable extender.
http://jsfiddle.net/neonms92/xybGG/
Extender:
ko.extenders.withPrevious = function (target) {
// Define new properties for previous value and whether it's changed
target.previous = ko.observable();
target.changed = ko.computed(function () { return target() !== target.previous(); });
// Subscribe to observable to update previous, before change.
target.subscribe(function (v) {
target.previous(v);
}, null, 'beforeChange');
// Return modified observable
return target;
}
Example Usage:
// Define observable using 'withPrevious' extension
self.hours = ko.observable().extend({ withPrevious: 1 });
// Subscribe to observable like normal
self.hours.subscribe(function () {
if (!self.hours.changed()) return; // Cancel if value hasn't changed
print('Hours changed from ' + self.hours.previous() + ' to ' + self.hours());
});
This seems to work for me
ko.observable.fn.beforeAndAfterSubscribe = function (callback, target) {
var _oldValue;
this.subscribe(function (oldValue) {
_oldValue = oldValue;
}, null, 'beforeChange');
this.subscribe(function (newValue) {
callback.call(target, _oldValue, newValue);
});
};
See more at: http://ideone.com/NPpNcB#sthash.wJn57567.dpuf
http://jsfiddle.net/MV3fN/3/
var sv = sv || {};
sv.PagedRequest = function (pageNumber, pageSize) {
var self = this;
self.pageNumber = ko.observable(pageNumber || 1);
self.numberOfPages = ko.observable(1);
self.pageSize = ko.observable(pageSize || sv.DefaultPageSize);
self.pageNumber.subscribe(function (previousValue) {
console.log(previousValue);
console.log(self.pageNumber.arguments[0]);
if (previousValue != _pagedRequest.pageNumber.arguments[0]) {
console.log('value changed');
}
else {
//This won't get executed because KO doesn't
//call the function if the value doesn't change
console.log('not changed');
}
}, _pagedRequest, "beforeChange");
};
var _pagedRequest = new sv.PagedRequest();
_pagedRequest.pageNumber(10);
_pagedRequest.pageNumber(20);
_pagedRequest.pageNumber(20);
_pagedRequest.pageNumber(5);
I don't know if you're really supposed to use arguments[0], but it seems to work.
You could also set up your own method to accomplish this in a much cleaner way:
http://jsfiddle.net/PXKgr/2/
...
self.setPageNumber = function(page) {
console.log(self.pageNumber());
console.log(page);
if (self.pageNumber() != page) {
console.log('value changed');
}
else {
console.log('not changed');
}
self.pageNumber(page);
};
...
_pagedRequest.setPageNumber(10);
_pagedRequest.setPageNumber(20);
_pagedRequest.setPageNumber(20);
_pagedRequest.setPageNumber(5);
I have problem with memory leak in nodejs when I added gzip support. I have wrote some code for tests. In code below I use zlib and I don't know why I have memory leak.
How I can improve this code to avoid memory leaking ? Anybody can help me ?
var
zlib = require('zlib'),
crypto = require('crypto');
var cacheList = {
article: {},
};
var timeoutId1, timeoutId2
console.log('process.pid: '+ process.pid);
clean = function()
{
var time = new Date().getTime();
timeoutId1 = setTimeout(function() { clean() }, 5000);
var countDeleted = 0;
for (id in cacheList.article) {
if (cacheList.article[id] && cacheList.article[id].timeExpire + 5000 < time) {
delete cacheList.article[id];
countDeleted++;
}
}
console.log('deleted: ' + countDeleted);
}
run = function()
{
var time = new Date().getTime();
timeoutId1 = setTimeout(function() { run() }, 5);
var md5 = crypto.createHash('md5');
md5.update('' + time);
var id = md5.digest('hex');
//console.log('id: ' + id);
var text = id+id+id+id+id+id+id+id +id+id+id+id+id+id+id+id +id+id+id+id+id+id+id+id +id+id+id+id+id+id+id+id +id+id+id+id+id+id+id+id +id+id+id+id+id+id+id+id +id+id+id+id+id+id+id+id +id+id+id+id+id+id+id+id;
zlib.gzip(text, function(err, result) {
if (!err) {
cacheList.article[id] = {
timeExpire: time + 10000,
data: text,
datagzip: result,
};
}
});
}
timeoutId1 = setTimeout(function() { run() }, 3000);
timeoutId2 = setTimeout(function() { clean() }, 5000);
change your two last lines to
timeoutId1 = run()
timeoutId2 = clean()
Since you already have the functions calling the setTimeout, by having another setTimeout, you are telling it to run another instance of that function (which in turn calls itself, so now you have it running twice, and so on).