How to block on asynchronous functions in JavaScript - javascript

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?

Related

ajax interface without then

I want to package a ajax call into an interface without then.
If i do like this, it will just return 'No ajax return';
var ajaxReturn = ajaxFunction();
function ajaxFunction(){
var text = 'No ajax return';
// get fileName using an ajax get
$.ajax();
return text;
}
If i do like this, it will be ugly for using then;
function ajaxFunction(){
var text = 'No ajax';
var dtd = $.Deferred();
$.ajax();
return dtd.promise();
}
$.when(ajaxFunction()).then();
I just want the interface to be simple and return the right thing, can i?
//return the right
var ajaxReturn = ajaxFunction();
function ajaxFunction(){
var text = 'No ajax';
var dtd = $.Deferred();
$.ajax();
return dtd.promise();
}
$.when(ajaxFunction()).then();
Whoa, what is all that? You do need .then but you don't need most of the surrounding stuff. $.ajax generates a promise for you. You don't need to make a promise object yourself. In fact, often the only reason you need to manually set up a Deferred/Promise directly is if you're using some library that sets up callbacks and doesn't use promises itself.
function ajaxFunction(){
return $.ajax();
}
ajaxFunction().then(function(data) { ... });
Now, let's say that you didn't actually want to return the JSON structure on the end of the ajax function; you want to take out just a number from inside of it, or tweak one value to make it an easier-to-use function for its callers. Easy enough:
function ajaxFunction(){
return $.ajax().then(function(data) {
return data[12].number;
}
}
ajaxFunction().then(function(number) { ... });
In direct answer to your question: No, what you asked for isn't possible. Whenever your JavaScript methods are running, the browser can't process other events like clicks and even basic scroll operations. So, any long-running operations (like contacting the server) do not return straight away, and instead offer a callback operation.
Well..., ajax is asynchronous so you either use .then() or use a callback logic... Doing synchronous ajax is not a option for me, so I won't even mention it.
The alternative to .then() would be something like this:
ajaxFunction(function(res){ // pass a function into it
// this will be called when the ajax is done
alert(res);
});
function ajaxFunction(callback){
// get fileName using an ajax get
$.ajax({
success: callback
});
}
But again, maybe you can use just a normal ajax callback pattern anyway
$.ajax({
...
success: function(res){
// use the res
}
});
Ajax is asynchronous. then is designed to make writing async operations look more similar to synchronous code and can actually be very elegant.
Additionally, $.ajax() returns a promise and is well suited to be written as follows:
function ajaxFunction(){
return $.ajax();
}
ajaxFunction().then(function(response){
// do whatever you want with the response
})
You simply can't write asynchronous code that way (ajaxResult = ajaxFunction()). The interpreter is going to keep trucking along line by line and ajaxResult will not be ready in time.
Read up on chaining $.Deferred's. It will really clean up your async code.

Javascript asynchronous assignment and callback

I'm sure there's an easy way to do this, but I'm having difficulty wrapping my mind around asynchronous calls and their flows. I'm trying to do a simple assignment statement in javascript, followed by setting a timer to perform operations on that object once it's been assigned. I have something along the lines of:
var info = getInfo();
$timeout(updateInfo(info), 5000);
However, I don't want the timeout to be executed until info is set initially. I've tried looking into using .then or some form of callback, but I haven't successfully determined how to do that. I'm unsure if having the parameter of info in the updateInfo call makes it so that I can't use callbacks in getInfo or what the correct flow is. I've read other articles and stack overflow responses, but couldn't find one dealing with asynchronous assignment and then using that as a paremter in a subsequent call.
getInfo and updateInfo are methods that return Highcharts graph config objects. Without copying over all the specific details:
getInfo: function() {
return {
options: {
chart: {
type: 'line'
}
}
...
}
}
updateInfo: function(info) {
// Here computations are performed on plot series data.
info.series.push(...)
}
Both getInfo and updateInfo looks pretty sync to me.
So there shouldn't be any synchronization problem.
The only thing I noticed is the wrong use of $timeout in your example.
$timeout(updateInfo(info), 5000); this way updateInfo will be called before the timeout starts and the returned value will be passed as a parameter.
In order to call updateInfo after 5 seconds you have to use anonymous function or bind function.
$timeout(function() { updateInfo(info); }, 5000);
$timeout(updateInfo.bind(null, info), 5000);
For more info about bind.
You should remember that although JavaScript does some asynchronous actions, yet the assignment to a variable is synchronous, which means that it occurs at the moment you requested for it, and won't go on to the next line until it's done.
If getInfo itself has the variable info in scope and updates it during the asynchronous call, then you shouldn't assign a value to it in the invocation of the function.
If I confused you, let me guess what you do there (and please provide the getInfo function for clarifying your question).
I'm pretty sure what getInfo does is an ajax call. So if you already use jQuery, you can simply use their ajax function:
function getInfo(){
$.ajax({
url: "/api/items"
}).done(updateInfo);
}
function updateInfo(data){
console.log ('Do something with', data);
}
getInfo();
See full documentation:
http://api.jquery.com/jquery.ajax/

Asynchronicity in Javascript

I have a question about asynchronicity in Javascript. From what I've been able to read up on about is that Javascript only uses one thread but is able to handle events asynchronously.
I have the following code:
game.next();
this.autopilot();
Now, I need the function game.next to finish before the this.autopilot function is called. Does Javascript actually wait until game.next is finished or does it run this.autopilot istantly?
If it does, does a callback solve the problem?
The next function with a callback:
Game.prototype.next = function(callback) {
// Code
if(callback !== undefined) {
callback();
}
};
The calling function using that callback:
game.next(function() {
this.autopilot();
}.bind(this));
In your code, game.next() must return before this.autopilot() is called.
However, it is possible that game.next() starts an asynchronous process (e.g., an Ajax call) and returns before the process completes. If you want to defer execution of this.autopilot() until that process is complete, then you would need some sort of callback mechanism. game.next() would have to pass the callback function on to whatever asynchronous processing was taking place. (Executing the call-back just before returning—as you suggest in your question—would be wrong, as this would also happen before the asynchronous process completed.)
Yes, you can use a callback to make sure game.next() finishes before this.autopilot(). But there is a trick: you just cannot paste some callback after whatever code. Whether or not you need to implement a callback depends on whether game.next() function is asynchronous.
Example of a synchronous function that doesn't need a callback:
function next() {
Game.x += 1;
}
Example of an asynchronous function that needs a callback to preserve the execution order:
function next(callback) {
window.setTimeout(function() {
if(callback !== undefined) { /* etc. */ }
}, 0);
}

How to use callback function in JavaScript functions

I am very new to JavaScript and need to use callback function in my java script function. I don't know how to use a callback function. Below is my code:
function SelectedFeature() {
// Here is my code call_Method1();
call_Method2();
}
The problem in the above function is that, call_method2() starts executing before call_Method1() ends its execution. To solve this problem, someone told me to use a callback function. Now how can I use callback function in my SelectedFeature() function? Please explain by using code sample.
I'm making an asynchronous request in call_method1(). I need call_Method2() should be called after completing execution call_method1(). But in my case, call_method2() calls before call_method1() completes its execution. Now how can I fix this?
You have to refactor call_method1() to accept and execute a callback after it finished execution:
call_method1(call_method2);
and
function call_method1(callback) {
// ...
// do asynchronous stuff, when the response is processed, call
if(typeof callback === 'function') {
callback();
}
// ...
}
Functions are first class citizens, so by referring to them by their name, you can pass them around like any other value.
We could help better if you post the code for call_method1.
What are you using to do your asynchronous call? Did you code it yourself or are you using a library like JQuery?
You could simply put a bool to say "working" that you set to true as method 1 starts and back to false when it finishes. you could then have method2 wait while working is true.
The question has already been answered above by Felix. Inspired by his answer and an issue I am having in a current project, I wrote a little gist that has a class that adds up a little extra safety.
To sum up, you pass a callback function just as the way you pass a variable. Then the receiver will trigger it as a function.
myCoolFunction: function( data ) {
// Do some thing with response
}
$.get( '/some/cool/url', myCoolFunction );
In the above $.get calls back myCoolFunction with the parameter data once the data is fetched
What happens if myCoolFunciton is a variable. Well it depends on how the receiver handles the input.
Just to be careful, I have a CoffeeScript class ( and its JavaScript compilation ) that will do some safety checks.
It doesn't do any thing magic, checks if its a function and returns, if not returns an empty function so that it would reduce possibility of JS error. https://gist.github.com/ziyan-junaideen/8717925

Pausing until a callback is called, in Javascript

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;
});
}

Categories