I'm trying to make this work, what am I doing wrong?
I want to be able to do some stuff when function one is completed.
function one() {
// do stuff
}
function main() {
//script
//script
one(function() {
// do some stuff when "one" is completed
console.log("one is completed");
});
}
Why this doest fire a callback? (no log entry in the console)
You need to pass the callback as an argument and call it like normal function
function one(a, b, fn) {
// do staff
if (fn) {
fn()
}
}
function main() {
//script
//script
one(5, 6, function() {
// do some stuff when "one" is completed
console.log("one is completed");
}
}
Cause one does not expect a callback, therefore it will be ignored and never called back.
function one(callback) { // <- take a callback
callback(); // <- call back the callback "callback"
}
You need to pass the callback function inside the one() function. Then you need to call that function:
const one = (cb) => {
console.log('in one()');
cb();
}
const main = () => {
one(() => {
console.log('one() is completed');
});
}
main();
OUTPUT:
in one()
one() is completed
Related
Pulling my hair out here trying to understand the infuriating nuances of Javascript. Hopefully some JS guru can take a gander, point and go, "well, there's yer problem...".
Here's a slimmed down sample of the problem:
var Parent = (function () {
var func1 = function () {
func2(function (res) {
console.log(res);
});
};
var func2 = function (callback) {
callback('abc');
};
return {
init: function () {
func1();
func2();
}
};
})();
Call with Parent.init();
This fails with the error:
Uncaught TypeError: callback is not a function
at check2 (<anonymous>:9:9)
at Object.init (<anonymous>:15:13)
at <anonymous>:1:8
What's getting me, is that if I comment out the enclosing code, like so, then it works as expected:
// var Parent = (function () {
var func1 = function () {
func2(function (res) {
console.log(res);
});
};
var func2 = function (callback) {
callback('abc');
};
// return {
// init: function () {
// func1();
// func2();
// }
// };
// })();
...and call with func1();
Result:
abc
What am I missing?
Thanks
In your version, you're calling func2() without specifying the callback function, which is a required argument. In your second example (with init commented out), you're correctly specifying the callback function in func2(function (res) { ... });.
Is the below snippet something you're looking for?
const Parent = (function () {
const func1 = function () {
func2(function (res) {
console.log(res);
});
}
const func2 = function (callback) {
callback('abc'); // this is passing 'abc' to line 3 of this snippet
}
return {
init: function () {
func1();
// func2(); // you don't want to call "func2" here, as "func1" calls it
// Or you could run:
func2(function (res) {
console.log(res);
});
// But this makes "func1" redundant
}
};
});
Parent().init();
// Output
abc
You have to pass callback parameter into func2 inside init. something like this.
init: function () {
func1();
func2(function (res) {
console.log(res);
});
}
From a comment on the question:
I just want to know why it works in the one sample, but not the other.
Because in one example you pass an argument to func2 and in the other you don't. Look at the working version:
func2(function (res) {
console.log(res);
});
vs. the non-working version:
func2();
The difference is that the first one passes a function which gets invoked as callback('abc'); whereas the second one passes nothing, so the attempt to invoke the non-existant callback function fails.
As an aside, in your non-working example you call func2 twice, once with the callback and once without. So it both "works" and "fails" in that case.
function make(callback) {
//some other manipulation to get data to pass it into $.post()
$.post(data, function(response) {
// do something
callback()
});
}
function two() {
make(function() {
console.log('hello');
});
}
console.log('hello') will still trigger first although I used callback. How to make make() run till everything is finished then trigger console.log('hello')?
Your code should work as soon as you call two().
This might visualize your situation better:
function requestSomething(callback) {
$.post(data, function(response) {
// do something
callback();
});
}
function callBackFunction() {
console.log('done!');
}
// Pass callBackFunction, which gets called after request.
requestSomething(callBackFunction);
I have 3 functions in my javascript code. I want to call the 3rd function as soon as both function1 and function2 are over executing.
func_one();
func_two();
func_three(); // To be called as soon both of the above functions finish executing.
Note that they may take variable time since function 1 and 2 are for fetching geolocation and some ajax request respectively.
How about this?
func_one() {
// Do something
func_two();
}
func_two() {
// Do something
func_three();
}
func_three() {
// Do something
}
There are two ways to solve this problem.The first one is to create callback functions as parameters for your existing functions.
function one(param_1 .. param_n, callback) {
var response = ... // some logic
if (typeof callback === "function") {
callback(response);
}
}
The second way is to use Promises like:
var p1 = new Promise(
function(resolve, reject) {
var response = ... //some logic
resolve(response);
}
}
var p2 = new Promise( ... );
p1.then(function(response1) {
p2.then(function(response2) {
//do some logic
})
})
You can try like this
var oneFinish = false;
var twoFinish = false;
function one(){
//...
oneFinish = true; // this value may depends on some logic
}
function two(){
//...
twoFinish = true; // this value may depends on some logic
}
function three(){
setInterval(function(){
if(oneFinish && twoFinish){
//...
}
}, 3000);
}
Since your functions func_one and func_two are making service calls you can call the functions on after other at the success callback of the previous function. Like
func_one().success(function(){
func_two().success(function(){
func_three();
});
});
I have been trying to figure out the Callback function feature in Javascript for a while without any success. I probably have the code messed up, however I am not getting any Javascript errors, so I supposed the syntax is somewhat correct.
Basically, I am looking for the getDistanceWithLatLong() function to end before the updateDB() begins, and then make sure that ends before the printList() function begins.
I have it working with a hardcoded "setTimeout" call on the functions, but I am overcompensating and forcing users to wait longer without a need if the Callback stuff would work.
Any suggestions? Below is the code:
function runSearchInOrder(callback) {
getDistanceWithLatLong(function() {
updateDB(function() {
printList(callback);
});
});
}
To accomplish this, you need to pass the next callback into each function.
function printList(callback) {
// do your printList work
console.log('printList is done');
callback();
}
function updateDB(callback) {
// do your updateDB work
console.log('updateDB is done');
callback()
}
function getDistanceWithLatLong(callback) {
// do your getDistanceWithLatLong work
console.log('getDistanceWithLatLong is done');
callback();
}
function runSearchInOrder(callback) {
getDistanceWithLatLong(function() {
updateDB(function() {
printList(callback);
});
});
}
runSearchInOrder(function(){console.log('finished')});
This code outputs:
getDistanceWithLatLong is done
updateDB is done
printList is done
finished
wouldn't this work:
function callback(f1, f2) {
f1();
f2();
}
As for passing arguments, be creative.
function1 = (callback1, callback2, callback3) => {
setTimeout(() => {
console.log("function 1 timed out!");
callback1(callback2, callback3);
}, 1500);
}
function2 = (callback1, callback2) => {
setTimeout(() => {
console.log("function 2 timed out!");
callback1(callback2);
}, 1500);
}
function3 = (callback1) => {
setTimeout(() => {
console.log("function 3 timed out!")
callback1()
}, 1500);
}
function4 = () => {
setTimeout(() => {
console.log("function 4 timed out!")
}, 1500);
}
function1(function2, function3, function4);
Just pass down the callbacks from the first function and execute each one, passing down the rest.
OUTPUT
function 1 timed out!
function 2 timed out!
function 3 timed out!
function 4 timed out!
In JavaScript, everything is an object, including functions. That is why you are able to pass callbacks as parameters - you are passing a function as if it were any other object.
In each function declaration, you need to run the callback.
function runSearchInOrder(callback) {
...
callback();
}
function getDistanceWithLatLong(callback) {
...
callback();
}
function updateDB(callback) {
...
callback();
}
Then your code posted above should work.
say I have 2 methods:
function A(callback) { ... }
function B(callback) { ... }
I want to execute:
function C();
after both A and B are finished.
what we usually do is to put function C in the callback like:
A(function() {
B(function() {
C();
});
});
now if both A and B takes a long time, I don't want B to execute after A has been finished. instead I want to start them at the same time to enhance performance.
what I'm thinking is to implement something like a semaphore (not really a semaphore of course), it fires an event after both A and B are finished. so that I can call C from within the event.
what I want to know is, is there any library implemented the above function already? I believe I'm not the first one who wants to do it.
any help is appreciated.
To expand on my comment...
async is a commonly used asynchronous flow control library for Node.js.
Its async.parallel() would probably do well for this:
async.parallel([
function(done) {
A(function () {
done(null);
});
},
function(done) {
B(function () {
done(null);
});
}
], function (err) {
C();
});
It's possible that this can be shortened, but it depends on how each function interact with callbacks and whether they follow the common Node.js pattern of error-first callbacks:
async.parallel([A, B], C);
For the sake of completeness and as mentioned above, the same result can be achieved using an external object to hold completion state where both A() and B() check to see if the other has completed and if so, invokes C(). As in:
var results={};
function onComplete(){
if(results['A'] && results['B'] && !results['C']) {
C();
}
}
function A(){
// ...
results['A']=true;
onComplete();
}
function B(){
// ...
results['B']=true;
onComplete();
}
The results object can be replaced by adding a 'isComplete' flag to both A() and B(), as in:
function A(){
// ...
A.isComplete=true;
onComplete();
}
And modifying onComplete to check this new flag:
function onComplete(){
if(A.isComplete && ...
}
Or, the same using events:
var util=require('util'),
events=require('events'),
EventEmitter=events.EventEmitter;
function F(){
EventEmitter.call(this); // init ancestor
}
util.inherits(F,EventEmitter); // assign ancestor
F.prototype.A=function(){
var self=this;
console.log('running A()');
setTimeout(function(){ // simulate long running code - 5 seconds
F.prototype.A.isComplete=true;
self.emit('complete','A');
},5000);
};
F.prototype.B=function(){
var self=this;
console.log('running B()');
setTimeout(function(){ // simulate long running code - 3 seconds
F.prototype.B.isComplete=true;
self.emit('complete','B');
},3000);
};
F.prototype.C=function(){
console.log('running C()');
};
var f=new F;
f.on('complete',function(which){ // onComplete handler
console.log(which+'() is complete');
if(F.prototype.A.isComplete && F.prototype.B.isComplete){
f.C();
}
});
// start it up
f.A();
f.B();
which, when run, will produce:
>node example.js
running A()
running B()
B() is complete
A() is complete
running C()
>
async.parallel([
function(){ ... },
function(){ ... }
], callback);
from: https://github.com/caolan/async
so in your case:
async.parallel([funcA,funcB],funcC);
//function definitions
function funcA() {...}
function funcB() {...}
function funcC() {...}
without modules i guess it would look something like this:
var numFuncs = 2;
A(D);
B(D);
and then
function D() {
if(numFuncs==0){ C(); } else {
numFuncs--;
}}
or like this:
A(D(C));
B(D(C));
function D() {
var x = process.funcsToCall= process.funcsToCall || {};
var f=arguments[0];
(!x.hasOwnProperty(f.name))?x[f.name]=0:x[f.name]++;
return function(){
(x[f.name]==0)?f():x[f.name]--;
}
}
If you're running on ES6, you can use Promise.all. Here is the example code rewritten:
Promise.all([
new Promise((resolve) => A(() => resolve())),
new Promise((resolve) => B(() => resolve())),
]).then(() => {
C()
}).catch(err => {
// handle errors from function A, B and C
})
we can aync and await for this purpose for example:
async function Foo(){
// function logic
}
and this Foo function as:
await Foo();