I have a function:
var inRendering = false;
function render() {
if (inRendering) {
requestAnimationFrame(render);
} else {
inRendering = true;
requestAnimationFrame(function () {
longAction();
inRendering = false;
});
}
}
I have to unit-test it. To test a situation of concurrent call of render.
Help me, please? Is such concurrent call ever possible in JavaScript? Thanks.
P.S. I wrote a test which obviously doesn't work (see comment): https://gist.github.com/kuraga/b0aa3d66fc0620f03b11
you can use async module, specifically async.parallel in order to run two functions in parallel
for example:
async.parallel([
function(callback){
// run your function once
},
function(callback){
// run your function the second time
}
],
// optional callback
function(err, results){
// the results array will equal ['one','two'] even though
// the second function had a shorter timeout.
});
Related
This is the function in question
function matches_password(password)
{
var modified = false;
var matched = false;
User.count({password : password}, function (err, result)
{
modified = true;
console.log('hei');
if (err)
{
//error
}
else
{
if (result)
{
matched = true;
}
}
});
while (!modified)
{
console.log('sleeping');
sleep.usleep(100000);
}
return matched;
}
As you can see, I have a callback that updates some variables; the main flow of execution is delayed until the callback is fired. The problem is that 'hei' never appears in the console.
Removing the while loop fixes the problem, but I need it, or else matched is always false.
What's going on and what can I do to get around this setback?
It looks like you're running into a asynchronous issue. you could try using a setTimeout function inside your while loop that calls User.count(...)
for how setTimeout works with Node: How does setTimeout work in Node.JS?
I think there is an easy solution for this, but for some reason I am not getting the expected results. My functions look like this:
var functionA = function(callback) {
loadData(fromURL1); // takes some time
loadData(fromURL2); // takes some time
callback(); // Should be called AFTER the loadData() functions are finished
}
var myCallBackFunction = function() {
// this function is called AFTER functionA() is finished
alert("All my loaded data from URL1 and URL2");
}
window.onload = function() {
functionA(myCallBackFunction);
}
Unfortunately, the callback() function above doesn't wait for loadData() to finish, and then just calls the alert with empty data.
I read a lot of online examples, but I think I am still missing something obvious.
If the loadData()s are async operations, you can do two things:
Using $.ajaxComplete():
var functionA = function(callback) {
loadData(fromURL1); // takes some time
loadData(fromURL2); // takes some time
$.ajaxComplete(function () {
callback(); // Should be called AFTER the loadData() functions are finished
});
}
Or chaining the functions:
var functionA = function(callback) {
loadData(fromURL1, function () {
loadData(fromURL2, function () {
callback(); // Should be called AFTER the loadData() functions are finished
}); // takes some time
}); // takes some time
}
Suppose I use Node.js to try to run two async calls to get some answers. I know there's an async package, where you can just pass two functions, and an optional callback.
async.parallel([fun1(){callback(null,1);},
fun2(){callback(null,2);}],
function(err, results) {
});
But suppose I have a priority now, if fun1 returns a value, then I do not need fun2's answer, only if fun1 returns null, then I wait for fun2. So I don't want to use the callback function, because the callback waits for both functions to finish, and fun2 may take very long.
Right now I just use a very exhaustive way by creating a callback function for both async calls.
function(){
var theAnswer,FromFun1,FromFun2;
var reply1,reply2;
fun1(reply1="answered";FromFun1=1;complete());
fun2(reply2="answered";FromFun2=2;complete());
function complete(answer){
if(reply1=="answered"){
theAnswer=FromFun1;
}else if(reply1==null){
// Don't do anything because fun1 is not finished running.
}else if(reply2=="answered"){
theAnswer=FromFun2;
}else{
// Both have no answer, err.
}
}
}
Is there a better way to do this?
The trick I've used for this scenario is to return "done" in first argument of the callback:
async.parallel([
function(callback){
callback("done",1);
},
function(callback){
callback(null,2);
}
], function(err, results) {
console.log(err, results); // done [ 1 ] or done [ 1 , 2 ]
});
Sounds like a hack and I don't usually do it but in some rare cases like this one, it actually keeps the code clean... just document it so that others know what you intention is.
Its better to use waterfall instead of parallel execution coz you can pass the result form your previous function to next one as argument.
async.waterfall([
function(callback){
callback(null, 'one');
},
function(arg1, callback){
// arg1 now equals 'one'
if(arg1==null){
// it will not take time it returns immediately
callback(null, 'done');
}else{
// do your another stuff here fun2 logic here
// it will not be executed and so it dont take time
}
}
], function (err, result) {
// result now equals 'done'
});
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I am in the process of relearning Javascript and last week when writing this code for a university assignment I think that there is probably a much better way of executing this code
app.get('/member/all', function(req, res) {
connection.query('CALL GetAllMembers()', function(err,rows){
connection.query('CALL CountMembers()', function(err, allMembers){
console.log(err);
connection.query('CALL CountAllIndMembers()', function(err,indMembers){
console.log(err);
connection.query('CALL CountInactiveMembers()', function(err,inactiveMembers){
console.log(err);
connection.query('CALL CountAllMembersInGroups()', function(err,groupMembers){
console.log(err);
res.render('members', {members : rows[0], title : "All Members", groupMembers : groupMembers[0][0].AllGrpMembers,
inactiveMembers : inactiveMembers[0][0].AllInactiveMembers, indMembers : indMembers[0][0].AllIndMembers,
allMembers : allMembers[0][0].AllMembers, statistics : true});
});
});
});
});
});
});
});
When I was trying to declare variables under the app.get such as var allMembers... when the callback was executed I was unable to set allMembers = rowsFromTheCallback. It seemed that it was a local variable to that callback. I'm sure this is something to do with the variable scope and/or hoisting. Just wanted to ask you guys if there would be a better way to do this as even though this function works. It is very ugly to look at haha!
Thanks in advance
Jack
As far as scope goes, all the inner functions should be able to read and write to the outer variable unless it is shadowed by an inner variable declaration or function parameter.
The problem you are having might be related to the async-ness of the code. See this code:
function delay(n, cb){
setTimeout(function(){ bs(delay) }, delay);
}
function main(){
var allMembers = 17;
delay(500, function(){
console.log(allMembers); // This looks at the outer "allMembers"
allMembers = 18;
delay(200, function(allMembers){ // <-- SHADOW
console.log(allMembers); // This looks at the allMembers from "delay 200"'s callback
allMembers = 42;
});
delay(300, function(){
console.log(allMembers); //This is the outside "allMembers" again
});
});
return allMembers; // Still 17!
}
main();
main will return before the setTimeouts have even fired so its going to return the original value of that variable. In order to wait for the inner callbacks to run, the only way is to make main take a callback to signa when its done, instead of just returning.
function main(onResult){
delay(500, function(){
//...
onResult(allMembers);
});
// <-- no return value
});
main(function(allM){
console.log(allM);
});
See async library: https://github.com/caolan/async
async.series([
getAllMembers,
countMembers,
...
], function(err, results) {
// err contains an error if any of the functions fails. No more functions will be run.
// results is an array containing results of each function if all the functions executed without errors
}));
function getAllMembers(callback) {
connection.query('CALL CountMembers()', callback);
}
function countMembers(callback) {
...
}
If the execution order of the functions does not matter, async.parallel can be used instead of async.series.
There is power in using a library to handle and encapsulate "Continuation Passing Style" (CPS) interactions with your asynchronous calls. The following code isn't from a library, but I'm going to walk through it and use it as an example of one way to implement CPS.
Setting up a scope appropriate queue is the first step. This example uses about the most simple method for doing so:
var nextList = [];
After that we need a method to handle our first case, the need to queue tasks to be performed in the future. In this case I was focused on performing them in order so I named it next.
function next() {
var todo,
current,
task,
args = {};
if (arguments.length > 0) { // if called with parameters process them
// if parameters aren't in an array wrap them
if (!Array.isArray(arguments['0'])) {
todo = [arguments];
} else { // we were passed an array
todo = [];
arguments['0'].forEach(function (item) {
// for each item we were passed add it to todo
todo.push(item);
});
}
nextList = todo.concat(nextList);
// append the new items to the end of our list
}
if (nextList.length > 0) { // if there are still things to do
current = Array.prototype.slice.apply(nextList.shift());
task = current[0];
args = current.slice(1);
task.apply(null, args); // execute the next item in the list
}
}
This allows us to make calls like:
.map(function (filepath) {
tasks.push(
[
handleAsset,
{
'path': filepath,
}
]
);
});
tasks.push([done]);
next(tasks);
This will call handleAsset, which is async, once for each file, in order. This will allows you to take your code and change each of the nested calls into a separate function in the form:
function memberAll() {
app.get('/member/all', function(req, res) {
if (err) {
handleError(err, 'memberAll');
} else {
next(getAllMembers, 'parameters to that call if needed');
}
});
}
where handleError is a common error handler, and the next call allows you to pass on relevant parameters to the next function that is needed. Importantly in the success side of the if statement you could either:
conditionally call one of several functions
call next with an array of calls to make, for instance if you had functions for processFolder and processFile you could expect that processing a folder might involve processing other folders and files and that the number would vary
do nothing except call next() with no parameters and end the current branch
Embellishments can include writing a clean function for emptying the nextList, adding items to nextList without calling an item from the list, etc. The alternative at this point is to either use an existing library for this or to continue writing your own.
Check out this code :
Link
<span>Moving</span>
$('#link').click(function () {
console.log("Enter");
$('#link').animate({ width: 200 }, 2000, function() {
console.log("finished");
});
console.log("Exit");
});
As you can see in the console, the "animate" function is asynchronous, and it "fork"s the flow of the event handler block code. In fact :
$('#link').click(function () {
console.log("Enter");
asyncFunct();
console.log("Exit");
});
function asyncFunct() {
console.log("finished");
}
follow the flow of the block code!
If I wish to create my function asyncFunct() { } with this behaviour, how can I do it with javascript/jquery? I think there is a strategy without the use of setTimeout()
You cannot make a truly custom asynchronous function. You'll eventually have to leverage on a technology provided natively, such as:
setInterval
setTimeout
requestAnimationFrame
XMLHttpRequest
WebSocket
Worker
Some HTML5 APIs such as the File API, Web Database API
Technologies that support onload
... many others
In fact, for the animation jQuery uses setInterval.
You can use a timer:
setTimeout( yourFn, 0 );
(where yourFn is a reference to your function)
or, with Lodash:
_.defer( yourFn );
Defers invoking the func until the current call stack has cleared. Any additional arguments are provided to func when it's invoked.
here you have simple solution (other write about it)
http://www.benlesh.com/2012/05/calling-javascript-function.html
And here you have above ready solution:
function async(your_function, callback) {
setTimeout(function() {
your_function();
if (callback) {callback();}
}, 0);
}
TEST 1 (may output '1 x 2 3' or '1 2 x 3' or '1 2 3 x'):
console.log(1);
async(function() {console.log('x')}, null);
console.log(2);
console.log(3);
TEST 2 (will always output 'x 1'):
async(function() {console.log('x');}, function() {console.log(1);});
This function is executed with timeout 0 - it will simulate asynchronous task
Here is a function that takes in another function and outputs a version that runs async.
var async = function (func) {
return function () {
var args = arguments;
setTimeout(function () {
func.apply(this, args);
}, 0);
};
};
It is used as a simple way to make an async function:
var anyncFunction = async(function (callback) {
doSomething();
callback();
});
This is different from #fider's answer because the function itself has its own structure (no callback added on, it's already in the function) and also because it creates a new function that can be used.
Edit: I totally misunderstood the question. In the browser, I would use setTimeout. If it was important that it ran in another thread, I would use Web Workers.
Late, but to show an easy solution using promises after their introduction in ES6, it handles asynchronous calls a lot easier:
You set the asynchronous code in a new promise:
var asyncFunct = new Promise(function(resolve, reject) {
$('#link').animate({ width: 200 }, 2000, function() {
console.log("finished");
resolve();
});
});
Note to set resolve() when async call finishes.
Then you add the code that you want to run after async call finishes inside .then() of the promise:
asyncFunct.then((result) => {
console.log("Exit");
});
Here is a snippet of it:
$('#link').click(function () {
console.log("Enter");
var asyncFunct = new Promise(function(resolve, reject) {
$('#link').animate({ width: 200 }, 2000, function() {
console.log("finished");
resolve();
});
});
asyncFunct.then((result) => {
console.log("Exit");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Link
<span>Moving</span>
or JSFiddle
This page walks you through the basics of creating an async javascript function.
Since ES2017, asynchronous javacript functions are much easier to write. You should also read more on Promises.
If you want to use Parameters and regulate the maximum number of async functions you can use a simple async worker I've build:
var BackgroundWorker = function(maxTasks) {
this.maxTasks = maxTasks || 100;
this.runningTasks = 0;
this.taskQueue = [];
};
/* runs an async task */
BackgroundWorker.prototype.runTask = function(task, delay, params) {
var self = this;
if(self.runningTasks >= self.maxTasks) {
self.taskQueue.push({ task: task, delay: delay, params: params});
} else {
self.runningTasks += 1;
var runnable = function(params) {
try {
task(params);
} catch(err) {
console.log(err);
}
self.taskCompleted();
}
// this approach uses current standards:
setTimeout(runnable, delay, params);
}
}
BackgroundWorker.prototype.taskCompleted = function() {
this.runningTasks -= 1;
// are any tasks waiting in queue?
if(this.taskQueue.length > 0) {
// it seems so! let's run it x)
var taskInfo = this.taskQueue.splice(0, 1)[0];
this.runTask(taskInfo.task, taskInfo.delay, taskInfo.params);
}
}
You can use it like this:
var myFunction = function() {
...
}
var myFunctionB = function() {
...
}
var myParams = { name: "John" };
var bgworker = new BackgroundWorker();
bgworker.runTask(myFunction, 0, myParams);
bgworker.runTask(myFunctionB, 0, null);
Function.prototype.applyAsync = function(params, cb){
var function_context = this;
setTimeout(function(){
var val = function_context.apply(undefined, params);
if(cb) cb(val);
}, 0);
}
// usage
var double = function(n){return 2*n;};
var display = function(){console.log(arguments); return undefined;};
double.applyAsync([3], display);
Although not fundamentally different than the other solutions, I think my solution does a few additional nice things:
it allows for parameters to the functions
it passes the output of the function to the callback
it is added to Function.prototype allowing a nicer way to call it
Also, the similarity to the built-in function Function.prototype.apply seems appropriate to me.
Next to the great answer by #pimvdb, and just in case you where wondering, async.js does not offer truly asynchronous functions either. Here is a (very) stripped down version of the library's main method:
function asyncify(func) { // signature: func(array)
return function (array, callback) {
var result;
try {
result = func.apply(this, array);
} catch (e) {
return callback(e);
}
/* code ommited in case func returns a promise */
callback(null, result);
};
}
So the function protects from errors and gracefully hands it to the callback to handle, but the code is as synchronous as any other JS function.
Unfortunately, JavaScript doesn't provide an async functionality. It works only in a single one thread. But the most of the modern browsers provide Workers, that are second scripts which gets executed in background and can return a result.
So, I reached a solution I think it's useful to asynchronously run a function, which creates a worker for each async call.
The code below contains the function async to call in background.
Function.prototype.async = function(callback) {
let blob = new Blob([ "self.addEventListener('message', function(e) { self.postMessage({ result: (" + this + ").apply(null, e.data) }); }, false);" ], { type: "text/javascript" });
let worker = new Worker(window.URL.createObjectURL(blob));
worker.addEventListener("message", function(e) {
this(e.data.result);
}.bind(callback), false);
return function() {
this.postMessage(Array.from(arguments));
}.bind(worker);
};
This is an example for usage:
(function(x) {
for (let i = 0; i < 999999999; i++) {}
return x * 2;
}).async(function(result) {
alert(result);
})(10);
This executes a function which iterate a for with a huge number to take time as demonstration of asynchronicity, and then gets the double of the passed number.
The async method provides a function which calls the wanted function in background, and in that which is provided as parameter of async callbacks the return in its unique parameter.
So in the callback function I alert the result.
MDN has a good example on the use of setTimeout preserving "this".
Like the following:
function doSomething() {
// use 'this' to handle the selected element here
}
$(".someSelector").each(function() {
setTimeout(doSomething.bind(this), 0);
});