I need to run a function on my node.js server, that completes the same task every 15 minutes.
I Used for that setInterval as in example number 3 here - http://tinyurl.com/c2jj7dl.
So, I got to something like this:
exports.start = function (list, callback){
setInterval(stuffTop.loadstuff, 900000, list, function (parsedList) {
// CODE STUFF HERE
// THEN THE CALLBACK.
callback(parsedDynamicList);
});
}
Actually this stuff work, but the function gets completed for the first time - only after 900000MS.
Is there an option to make to function complete (in the first round) - straight when called ? Thanks.
Use a function which recursivly calls itself:
foo = function(){
doStuff()
setTimeout(foo,900000)
}
In your case It would look like this:
exports.start = function (list, callback){
var foo = function () {
stuffTop.loadstuff(list, function(parsedList) {
//CODE STUFF HERE
//THEN THE CALLBACK
callback(parsedDynamicList);
setTimeout(foo,900000);
});
}
foo();
}
The solution to your question is simple. Call the function before going into the setInterval. Like this:
var callback=function(){}
var list=['some','list'];
var repeaterFunction = function(){console.log("do now!")}
var start = function (list, callback){
repeaterFunction();
var repeater = setInterval(repeaterFunction, 5000, list, function(parsedList){
// CODE STUFF HERE
// THEN THE CALLBACK.
callback(parsedDynamicList);
});
}
start()
The fact that I use var repeater = setInterval(... allows for the clearInterval(repeater) whenever you wish.
Here's the fiddle
Related
Right im trying to get progress from a list of tasks run through async series
module.exports = update;
function update(){
// Require Deps
var async = require('async');
var progress = require('progress);
var tasks = [task1,task2,task3];
// Create the progress bar using the list of tasks
// as the length of the bar
var bar = new progress(':current/:total [:bar] :task', {
total: tasks.length
});
//Run async series using the array of tasks
async.series(tasks,function(err,result){
// Do something with the results or errors
})
};
var task1 = function(callback){
callback();
};
var task2 = function(callback){
callback();
}
This is a very simple version of my code.
The Question
How can i pass the bar to each of the functions or 'through' the functions and callbacks to that on success of each task im able to use
bar.tick({'task': tasks[bar.curr]});
everything i try I get bar not defined so tried passing bar into the functions with the callback function(callback, bar) and then i get tick not defined
Im new to nodeJs and well js all together so please be gentle
NOTE what im trying to achieve is to complete a list of functions displaying the current task in a progress bar
Ive read the docs and looked at the examples for progress and of async but still can;t make heads or tails of it
Am I close or is there a better way
You should add bar.tick, every time you want to update the current task in the taskbar. For example:
var task1 = function(callback){
bar.tick({bar:'Finish First Task'})
callback();
};
All your functions (task1,task2) should be declared INSIDE of update function, otherwise they will not be able to access the bar variable.
It's little complicated, I'm sorry. What we doing is to make new function instead of the functions in the array. The new function we call the original function, and when the original function finish (callback), it will call the progress.tick, after that it will run the original callback function.
var tasks=[task1,task2,task3]
for (var i in tasks){
(function(orgFunc,i){ // This Function will be run on task1,task2,task3. `i` will be 0,1,2, `orgFunc` will be the original function.
tasks[i]=function(next){ // Replace the original function with new function
orgFunc(funtion(){ // Call the original function
bar.tick({bar:'Finish Task #' + i})
next.apply(null,arguments) // Call the callback.
})
}}).bind(null,tasks[i],i)
}
I am not sure its the best solution, but when doing having callbacks and requesting a result, I have some kind of counter which I then check in my "final" callback:
i.e. have a global (before function update())
var tasksStatus = {task1:false,task2:false,task3:false};
and then in each task function set that
var task1 = function(callback){
tasksStatus.task1 = true;
callback();
};
Then you can check the global variable for which task is done and act accordingly.
Edit: a sample callback could be:
callback = function () {
var status = 0;
for(var s in tasksStatus) {
if(tasksStatus[s])
status += 33;
}
// update progress
if(status == 99) {
// done....
}
}
I am working with a transnational framework within Javascript. So I need to wait for the previous query to finish before I move on. For example...
// Explicit this won't work because the length is not static
var i = [1,2,3]
doSomething(i[0], function(){
doSomething(i[1], function(){
doSomething(i[2], function(){
commitTransaction()
}
})
})
From this example I can't figure out a way to do this dynamically. It feels like a queue/recursion problem but I can't seem to crack it.
Does anyone else have an idea? I can also wrap in promises so that is an option as well, although that seems less synchronous.
Use async.eachSeries. So your code would translate to:
var transaction = {...};
async.eachSeries([1, 2, 3], function(value, callback) {
doSomething(value, transaction, callback);
}, function(err) {
if(err) throw err; // if there is any error in doSomething
commitTransaction(transaction);
});
jsFiddle Demo
I would suggest making a queue to do this. It would take the array, the generic callback function and a final function to callback with. Basically, the best way to accomplish this is to allow your functions to expect to have values injected.
The core assumption is that it is understood the caller will allow their callback function to have the current value and next callback function injected. That basically means we will end up with a function I have named queueAll which looks like this
function queueAll(arr,cbIteration,final){
var queue = [function(){ cbIteration(arr[arr.length-1],final) }];
for(var i = arr.length-2; i > 0; i--){
(function(next,i){
queue.unshift(function(){ cbIteration(arr[i],next) });
})(queue[0],i)
}
cbIteration(arr[0],queue[0]);
}
It takes the final call, places it in the queue, and then iterates, placing subsequent callback functions in the queue with the current value closed over, as well as closing over the front of the queue which at that point is the next call back. It is fairly simple to use. Pass it an array, a callback which expects values to be injected, and a final function.
In your case it would look like
queueAll(i,function(item,next){
doSomething(item,next);
},function(){
commitTransaction();
});
Stack Snippet Demo
//## <helper queue>
function queueAll(arr,cbIteration,final){
var queue = [function(){ cbIteration(arr[arr.length-1],final) }];
for(var i = arr.length-2; i > 0; i--){
(function(next,i){
queue.unshift(function(){ cbIteration(arr[i],next) });
})(queue[0],i)
}
cbIteration(arr[0],queue[0]);
}
//## </helper queue>
//## <user defined functions>
function doSomething(val,callback){
setTimeout(function(){
console.log(val);
callback();
},val*10);
}
function commitTransaction(){
console.log("commit");
}
//## </user defined functions>
//## <actual use>
var arr = [10,20,30];
queueAll(arr,function(item,next){
doSomething(item,next);
},function(){
commitTransaction();
});
//## </actual use>
Actually, I think promises are exactly what you're looking for. But for a traditional callback approach, consider the following:
var state = false,
doSomething = function (value, callback) {
/* do stuff with value */
if (!state)
doSomething(newValue, callback);
else
callback();
};
Is there a possibility to make some delay? I call a function in a while loop. This function calls executeQueryAsync which has to finish before the loop continues. When I use an alert my code works but without it doesn't.
while (listPermsEnumerator.moveNext()) {
enumG = groups.getEnumerator();
var rAssignment = listPermsEnumerator.get_current();
var member = rAssignment.get_member();
var groupCounter = 1;
var name = '';
//alert(''); This alert makes code work
while (enumG.moveNext()) {
var group = enumG.get_current();
var groupname = group.get_title();
//alert(groupname);
if (member.get_title() === groupname) {
name = groupname;
SP.SOD.executeOrDelayUntilScriptLoaded(function(){
retrieveAllUsersInGroup(groupname, groupCounter, groups);
}, key);
}
groupCounter++;
}
roleAssignment = this.listRoleAssignments.getByPrincipalId(member.get_id());
roleBindings = roleAssignment.get_roleDefinitionBindings();
// in checkPermission() another executeQqueryAsync is called
checkPermission(context, roleAssignment, roleBindings, name);
}
...
function checkPermission(context, roleAssignment, roleBindings, name) {
this.name = name;
context.load(roleAssignment);
context.load(roleBindings);
context.executeQueryAsync(Function.createDelegate(this, Bind), Function.createDelegate(this, BindFail));
}
The simplest solution would be to code your methods in a way that reflects the purpose of asynchronous operations. You seem to be trying to work around the ExecuteQueryAsync and trying to "make" it synchronous.
Here is a similar example -- see the 2nd answer: ( https://sharepoint.stackexchange.com/questions/95907/executequeryasync-in-for-loop ) Basically you a) write the callback function inline, and b) you put the loop in the success callback.
(What's great about writing the "success" callback function in line is the success callback function then has access to all the variables in the method. It's a closure).
If you need to loop through an array of asynchronous jobs, you can do something like this:
var reports = [11, 12, 14, 15];
function doTheReport() {
if (reports.length === 0) {
alert('All reports are done now.');
return;
}
var report_Id = reports.pop();
$.ajax({
url: "/DoTheReport",
complete: function () {
doTheReport();
}
});
};
I am trying to figure out how to work with a closure function.
On a click event, I want to determine values of parm1 and parm2 and display them in a div,
then update new values to an table with an SQL statement.
If user clicks repeatedly, I want to throttle (debounce) and only perform SQL update 5 seconds after user stops clicking. However, display of parm1 and parm2 should occur on each click.
I am unsure of how to pass the parms to the SQL process.
(function() {
// create debounced function
var d_process = $.debounce(SQLprocess, 5000);
$('#myButton').click(function() {
// determine parameters
var parm1 = 1 + 1; // edit: added var
$(".div_1").text(parm1);
var parm2 = 2+2; // edit: added var
$(".div_2").text(parm2);
d_process();
});
}());
function SQLprocess(parm1, parm2) {
//perform an SQL update
}
Reference:
http://code.google.com/p/jquery-debounce/
To pass SQLprocess with parameters to the debounce function, change this:
var d_process = $.debounce(SQLprocess, 5000);
to this:
var d_process = $.debounce(function() {SQLprocess(parm1, parm2)}, 5000);
This creates an anonymous function with no parameters that is passed to debounce. But that anonymous function calls SQLprocess with the right parmeters.
Some people ask why you can't do this:
var d_process = $.debounce(SQLprocess(parm1, parm2), 5000);
The answer is because, in the Javavscript language, SQLprocess(parm1, parm2) is a function call. It will execute that function immediately and pass the return value to $.debounce() which is not what you want. $.debounce is expecting a function with no arguments so that's what you have to pass it. The way to get your arguments to SQLprocess is to wrap that in a function that has no arguments. It does not have to be an anonymous function. It could also be like this with a named function if you want:
function myFunctionWrapper() {
SQLprocess(parm1, parm2);
}
var d_process = $.debounce(myFunctionWrapper, 5000);
This question already has answers here:
Semaphore-like queue in javascript?
(4 answers)
Closed 6 years ago.
I have created a Queue class in javascript and I would like to store functions as data in a queue. That way I can build up requests (function calls) and respond to them when I need to (actually executing the function).
Is there any way to store a function as data, somewhat similar to
.setTimeout("doSomething()", 1000);
except it would be
functionQueue.enqueue(doSomething());
Where it would store doSomething() as data so when I retrieve the data from the queue, the function would be executed.
I'm guessing I would have to have doSomething() in quotes -> "doSomething()" and some how make it call the function using a string, anyone know how that could be done?
All functions are actually variables, so it's actually pretty easy to store all your functions in array (by referencing them without the ()):
// Create your functions, in a variety of manners...
// (The second method is preferable, but I show the first for reference.)
function fun1() { alert("Message 1"); };
var fun2 = function() { alert("Message 2"); };
// Create an array and append your functions to them
var funqueue = [];
funqueue.push(fun1);
funqueue.push(fun2);
// Remove and execute the first function on the queue
(funqueue.shift())();
This becomes a bit more complex if you want to pass parameters to your functions, but once you've setup the framework for doing this once it becomes easy every time thereafter. Essentially what you're going to do is create a wrapper function which, when invoked, fires off a predefined function with a particular context and parameter set:
// Function wrapping code.
// fn - reference to function.
// context - what you want "this" to be.
// params - array of parameters to pass to function.
var wrapFunction = function(fn, context, params) {
return function() {
fn.apply(context, params);
};
}
Now that we've got a utility function for wrapping, let's see how it's used to create future invocations of functions:
// Create my function to be wrapped
var sayStuff = function(str) {
alert(str);
}
// Wrap the function. Make sure that the params are an array.
var fun1 = wrapFunction(sayStuff, this, ["Hello, world!"]);
var fun2 = wrapFunction(sayStuff, this, ["Goodbye, cruel world!"]);
// Create an array and append your functions to them
var funqueue = [];
funqueue.push(fun1);
funqueue.push(fun2);
// Remove and execute all items in the array
while (funqueue.length > 0) {
(funqueue.shift())();
}
This code could be improved by allowing the wrapper to either use an array or a series of arguments (but doing so would muddle up the example I'm trying to make).
Canonical answer posted here
Here is a nice Queue class you can use without the use of timeouts:
var Queue = (function(){
function Queue() {};
Queue.prototype.running = false;
Queue.prototype.queue = [];
Queue.prototype.add_function = function(callback) {
var _this = this;
//add callback to the queue
this.queue.push(function(){
var finished = callback();
if(typeof finished === "undefined" || finished) {
// if callback returns `false`, then you have to
// call `next` somewhere in the callback
_this.next();
}
});
if(!this.running) {
// if nothing is running, then start the engines!
this.next();
}
return this; // for chaining fun!
}
Queue.prototype.next = function(){
this.running = false;
//get the first element off the queue
var shift = this.queue.shift();
if(shift) {
this.running = true;
shift();
}
}
return Queue;
})();
It can be used like so:
var queue = new Queue;
queue.add_function(function(){
//start running something
});
queue.add_function(function(){
//start running something 2
});
queue.add_function(function(){
//start running something 3
});
Refer to the function you're storing without the () at the end. doSomething is a variable (that happens to be a function); doSomething() is an instruction to execute the function.
Later on, when you're using the queue, you'll want something like (functionQueue.pop())() -- that is, execute functionQueue.pop, and then execute the return value of that call to pop.
You can also use the .call() method of a function object.
function doSomething() {
alert('doSomething');
}
var funcs = new Array();
funcs['doSomething'] = doSomething;
funcs['doSomething'].call();
In addition, you can also add the function directly to the queue:
funcs['somethingElse'] = function() {
alert('somethingElse');
};
funcs['somethingElse'].call();