I'm fairly new to the callback-style of programming in javascript.
Is there a way to force code to wait until a function call finishes via a callback?
Let me explain.
The following function takes a number and returns a result based upon it.
function get_expensive_thing(n) {
return fetch_from_disk(n);
}
So far, easy enough.
But what do I do when fetch_from_disk instead returns its result via a callback?
Like so:
function get_expensive_thing(n) {
fetch_from_disk(n, function(answer) {
return answer; // Does not work
});
}
The above doesn't work because the return is in the scope of the anonymous function,
rather than the get_expensive_thing function.
There are two possible "solutions", but both are inadequate.
One is to refactor get_expensive_thing to itself answer with a callback:
function get_expensive_thing(n, callback) {
fetch_from_disk(n, function(answer) {
callback(answer);
});
}
The other is to recode fetch_from_disk, but this is not an option.
How can we achieve the desired result
while keeping the desired behaviour of get_expensive_thing
-- i.e., wait until fetch_from_disk calls the callback, then return that answer?
Pretty much there's no "waiting" in browser Javascript. It's all about callbacks. Remember that your callbacks can be "closures", which means definitions of functions that "capture" local variables from the context in which they were created.
You'll be a happier person if you embrace this way of doing things.
add in that missing return :)
function get_expensive_thing(n) {
return fetch_from_disk(n, function(answer) {
return answer;
});
}
Related
I realise this is more of a general question, but I've read through similar answers on here but I can't find more of an overview. I'm new to callbacks and I'm trying to understand when they should be used.
The MDN web docs has this example;
function greeting(name) {
alert('Hello ' + name);
}
function processUserInput(callback) {
var name = prompt('Please enter your name.');
callback(name);
}
processUserInput(greeting);
However I'm struggling to see how this is more beneficial than the following, where I'm not passing the greeting function as a parameter?
function greeting(name) {
alert('Hello ' + name);
}
function processUserInput() {
var name = prompt('Please enter your name.');
greeting(name);
}
processUserInput();
As Javascript is async, sometimes it is difficult to handle response from non-blocking functions, for ex. if you are making an ajax call then it'll be executed asynchronously and results will be returned sometime later, by that time the main execution flow will pass the ajax code and starts executing following statements, in that case, its very difficult to catch the response to process further.
To handle those cases, callbacks comes into picture where you pass a function as the parameter to the ajax function and once the response is returned then call the callback by passing response data as a parameter to process further.
more info here http://callbackhell.com/
In simple terms you can say a callback is a way of asking a question (or requesting a task) in advance, i.e. when you're done with this do this (usually with the result). The whole point is to set aside functions that are to be done later, usually because you don't have the required inputs to do them now.
The 2 main differences between your implementation and the MDN one is that yours is harder to maintain and harder to reason about hence test.
1. Maintanance / Reusability
Imagine you're a few thousand lines of code into a code base then you're required to change what processUserInput() does. Its much easier to change or write a new callback function instead of changing the function processUserInput(). This would be evident if processUserInput was a bit more complicated. This also means the MDN one is much more useful in various scenarios unlike your implementation. You can reuse it in different situations like saying good bye, capitalizing names etc simply by writing different callbacks to plug into processUserInput().
2. Testing / Easier to reason about
The MDN implementation is much more easier to understand. Its easier to assume that the function processUserInput(greeting) will probably return a greeting than it is to assume what processUserInput() does. This makes it easier to test because you can always be sure the MDN implementation will always return the same output given an input.
Callbacks can be extremely useful depending on the circumstances; for example, when working with JavaScript for Google Chrome browser extension development, a callback can be used for intercepring web requests once it has been setup.
The purpose of a callback in general is to have the callback routine executed upon a trigger - the trigger being an event of some kind. Usually, functionality follows an interface of chained APIs. By implementing callback support, you can redirect execution flow during a stage of an operation. Callbacks are especially useful to third-party developers when dealing with someone elses library depending on what they are trying to do. Think of them like a notification system.
Functions in general taking in parameters is useful for flexibility and maintenance. If you use different functions for different things, the functions can be simply re-used over and over again to provide different functionality - whilst still preventing bloating the source code with more-or-less the same code over and over again. At the same time, if you use functions to your own library and a bug shows up, you can simply patch it for the one function and then it will be solved.
In your example, your passing a callback routine to the function you're calling - the function you're calling will call the callback function and pass the correct parameters. This is flexible because it allows you to have a callback routine called for printing the contents of the variable, and another for calculating the length of the string passed in, or another for logging it somewhere, etc. It allows you to re-use the function you setup, and have a different function called with the correct parameters without re-making the original function.
This example is not appropriate for understanding callbacks
In simple Language callbacks functions are used when we have to do some stuff after or in response of some other event or function or expression.
i.e when the parent function completes its execution then callback gets executed.
simple Example
function hungerStatus(status,cb){
return cb(status)
}
function whatToDo(status){
return status ? "order Pizza" : "lets play"
}
hungerStatus(false,whatToDo)
Another example
// global variable
var allUserData = [];
// generic logStuff function that prints to console
function logStuff (userData) {
if ( typeof userData === "string")
{
console.log(userData);
}
else if ( typeof userData === "object")
{
for (var item in userData) {
console.log(item + ": " + userData[item]);
}
}
}
// A function that takes two parameters, the last one a callback function
function getInput (options, callback) {
allUserData.push (options);
callback (options);
}
// When we call the getInput function, we pass logStuff as a parameter.
// So logStuff will be the function that will called back (or executed) inside the getInput function
getInput ({name:"Rich", speciality:"JavaScript"}, logStuff);
refer callback exaplanation
I've been trying to read as much as I can about javascript callbacks and jquery deferred objects but apparently things just aren't clicking for me. It seems to make a vague amount of sense when I read through it and practice examples, but when I try to apply it to my specific problem, I'm just hitting a wall. If anyone can understand what I'm trying to do and offer ideas, it would be much appreciated!
Here's some existing code:
$(document).ready(function() {
firstFunction();
secondFunction();
});
For the sake of keeping things simple here, I won't get into what firstFunction() and secondFunction() do, but suffice it to say that they both perform asynchronous work.
Here's my problem:
firstFunction() is dependent on the document being ready so needs to be inside $(document).ready(function() { }. secondFunction() isn't dependent on $(document).ready(function(), but should only execute after firstFunction has completed. I'm hoping to do all the computation for secondFunction() before the $(document).ready(function() { } block, but only execute it after firstFunction() has completed. This way firstFunction and secondFunction will execute in a more visually seamless manner. So basically, I'd like to do something like the following pseudo code:
var deferredSecondFunction = secondFunction().compute().defer(); //perform computation for secondFunction but defer execution
$(document).ready(function() {
firstFunction().done.execute(deferredSecondFunction().execute()); //finally execute secondFunction once firstFunction has completed.
});
Does anyone know if this is even possible? An important caveat is that I need to do this without the Javascript Promise object, since, for reasons outside the scope of this question, the webkit I'm working with is an old version. If anyone could help me understand this it would be appreciated!
The code shown uses a callback function and a self-invoking anonymous JavaScript function such has:
var calculatedObject;
(function(){
// Will be executed as soon as browser interprets it.
// write code here & save your calculations/operations
calculatedObject = { ... };
})();
function firstFunction(callback){
// Do stuff
callback();
}
function secondFunction(){
// Do more stuff
// Use your calculations saved in the calculated object.
}
$(document).ready(function(){
firstFunction(secondFunction);
});
This way the second function will only be called at the end of the first one.
you can use a callback..
function f1(){
//do some stuff
}
function f2(callback){
// do some async stuff
callback();
}
f2(f1);
this example passes one function to another function. the second function then calls the first whenever it's ready.
Note : No jQuery
I have four functions and I want to call them one after another ie. call a function after the previously called function is executed (in core js, not jquery). I tried searching in the internet but I could not find a satisfied answer. Here is what I've done so far :
function func1() {
noAjaxCall.click();
return true;
}
function func2() {
ajaxCall.click(); <--------- sending an ajax request
return true;
}
function func3() {
noAjaxCall.click();
return true;
}
function func4() {
//anything here
}
if(func1())
if(func2())
if(func3())
func4();
What happens is that, func3 is not called. Why this happens and any work around to this?
Thanks!
I'm sure you're not doing what you expect.
The AjaxCall is not really done when func3 will be called, cause... it's asynchronous.
I prefere you find the real solution (what you really wanna do) than trying to solve this problem.
Could you give the real goal you try to achieve?
edit
Let's imagime the handle on 'click' for ajaxCall. I know u don't have jQuery on the app but I create what I know.
function requester(){
//do some asyn work
$.ajax({ //...
success: function() {
//HERE call the other functions
}
});
}
im not very familiar with callback functions in javascript and how they handle data.
i want to achieve something like this in google chrome
function getBookmarkBar()
{
chrome.bookmarks.getChildren('1',function(bookmarkNodes)
{
return bookmarkNodes;
});
}
function getOtherBookmarks(folderId)
{
chrome.bookmarks.getChildren(folderId,function(bookmarkNodes)
{
return bookmarkNodes;
});
}
function doprocessing(){
{
bookmarkbarNodes=getBookmarkBar();
otherNodes=getOtherBookmarks('2');
//do some processing for bookmarkbarNodes and otherNodes
}
is there a way possible(or as close as possible) to do this ?
right now i do this by a single function but that would be a bad idea because of coupling of retrieval and modification logic:
function process{
chrome.boomarks.getChildren('1',function(bookmarkNodes){
chrome.bookmarks.getChildren('2',function(otherNodes){
//do processing
});
});
writing above code in generic function would make it highly reusable.
There is no way to synchronize functions. Also, it is a bad idea to do that becaus you would block the program until the function is fully executed.
Callbacks are a great thing. There is a good reason why the API is totally asynchronus.
They don't want you to synchronize the functions.
I need to write a function in JavaScript, which returns a state from calling an asynchronous function. However, the caller only receives the value and no callback function is to be provided. I tried something like:
function getState() {
var ret = null;
asyncCall("request",
function() { ret = "foo"; } // callback
);
while (ret === null)
; // block on the asynchronous call
return ret;
}
However, the loop is never going to end…
Any ideas? Thank you.
I think you're looking for StratifiedJS, http://stratifiedjs.org
It allows you to "orchestrate" your async code exactly like you wrote, BEWARE that it "writes" like synchronous code, it will NOT block the rest of your application.
You can use it anywhere by loading the apollo js library.
This is how it would look like in Stratified JavaScript:
function getState() {
waitfor (var ret) {
// block on the asynchronous call
asyncCall("request", resume);
}
return ret;
}
of course there are modules/libraries that would just make it look like this:
http://onilabs.com/modules#http
function getState() {
return http.get("request");
}
Why not just:
asyncCall("request", function() {
// here you can inspect the state
});
What's the point of the wrapper function?
Asynchronous functions work this way. If you want to block the execution, then use a synchronous call:
var state = syncCall("request");
The best would be to put the logic you want to have called into the callback function. Is there any reason why you can't do that?
You could use setInterval to check on the result, but that requires a callback function, too...
Unless I misunderstood your question, you could look at jQuery's ajaxStop() event - http://api.jquery.com/ajaxstop. This blocks until all ajax calls have completed. This obviously requires that all of your async calls be done thru jQuery.
$(document).ajaxStop(function() {
// do your "ajax dependent" stuff here
});
what you are trying to do is a synchronous call, so its not a good idea to do it with a function designed for asynchronous call.
You have an answer here : How can I get jQuery to perform a synchronous, rather than asynchronous, Ajax request?