I have 3 function calls in a method where all of them have a asynchronus ajax call in them. All these three functions returns a bool always true.
So in my code i have:
a();
wait(100ms);
b();
wait(100ms);
c();
At the moment i have a wait function, but instead i would like to have a promise or something, so i trigger b when a is done. All the three functions have asynchronus ajax calls in them, but return true before the ajax calls is done.
I would like to rewrite the code, but thats no option atm. due to a lot of this code is used everywhere...
I guess passing a callback to the function and call it after the execution will make a difference. For example...
function a(cb) {
ajaxfunction(
.. stuff to do
cb(param)
);
}
a(function(param){
})
If you always want to run these three functions, regardless of their return value, you could as well use setTimeout() to run them without using wait().
Related
I have a component in React that receives 2 functions as props, they work pretty well. However, I need to call them one after another, as promises. By now I am calling them as:
this.props.function1();
this.props.functions2();
But they are called in parallel, I tried:
let whenfirst =this.props.function1();
whenfirst.then(this.props.function2());
But then I get: TypeError: whenfirst is undefined
I really cannot make modifications over function1, so how is the easy way to execute the function2 after function1 is completed?
EDIT: Sorry, I missed the crucial part where you said you can't change function1. Ignore the rest.
So I'm guessing function1 looks something like this
function function1() {
// make the POST call
someAJAXLibrary.post('someUrl', maybePostData);
// Do nothing.. post is doing its work and maybe
// you didn't care about the return
}
Which means you can't know when the POST call is done. But the library POST call probably does return a Promise (that's pretty standard), you just don't use it.
So instead do
function function1() {
return someAJAXLibrary.post('someUrl', maybePostData);
}
Now you can use it like you first thought, in your component.
let whenfirst = this.props.function1();
whenfirst
.then(useMeOrNot => this.props.function2());
I have some javascript functions being called on Document Ready:
fogFields();
getLoS();
getShips();
startGame();
getNextMove();
However, it is as though getNextMove() is being called first, most likely as all it does is an ajax call and alerts the result. All the other functions have more work, so, the first thing that happens on load is the getNextMove() alert, and in the background you can see that none of the other functions did their work. Until I click OK on the alert window, no results are shown. Can I make it so that until a function finishes, the next wont even start. Some functions call their own extra functions before they finish, and that works in order, but I cant do that with the whole code...
Given the code in your question, there is no way the call to getNextMove can be invoked before startGame has been exited, regardless of their contents.
It may be true that a function that has been scheduled asynchronously (via timeout, AJAX callback etc.) within startGame completes at any time before or after the invocation of getNextMove, but this is a separate issue. To resolve that issue we need to know more about the contents of the functions.
If the other functions have an AJAX call in them, then these AJAX calls most certainly take a callback argument, which is a function that gets executes, when the AJAX call has finshed. Now, if you want to execute your functions in a way, the one function starts when the AJAX call of the previous function finished, you can add an additional callback argument to your own functions, which will then be passed to the AJAX calls. This should illustrate what I mean:
function logFields(callback) {
ajaxCall(callback);
}
function getLoS(callback) {
ajaxCall(callback);
}
function getShips(callback) {
ajaxCall(callback);
}
function startGame(callback) {
ajaxCall(callback);
}
function getNextMove() {
}
fogFields(function(){
getLoS(function(){
getShips(function(){
startGame(function(){
getNextMove();
});
});
});
});
If all of your functions use a ajax call then just use promises.
Simply return it, for example:
function fogFields(){
return $.ajax();
};
and then just use .then:
fogFields().then(getLos());
more information about deffered object on jquery doc page if you use it.
Or implementation in pure javascript you can find here and more theory here.
or another option, which I will not recommend you is to set async param in $.ajax call to false. Again it's for case you use jQuery.
I have 2 functions. The second one is faster than the first one,how could the function wait to complete first one's work?
function1(); // slow
function2(); // fast
JavaScript is imperative and single-threaded, it just works like this. function2() won't start until function1() finishes.
If by slow you mean calling asynchronously some external service via AJAX, then we're talking. function1() must provide some sort of callback so that when asynchronous request finishes, function2() is called:
function1(function2);
The implementation is trivial, e.g. using jQuery:
function function1(callback) {
$.ajax({url: 'some-url'}).done(callback);
}
If functions are to be called asynchronously, aside from the obvious callback approach, their sequencing could be based on the events framework. You could add an event listener with function1 as a handler, and trigger that event within function2.
You must be using some AJAX request. So, after ajax complete call callback function like:
function1 = new function(callback) {
$.ajax({...}).done(callback());
}
function1(function2);
If your calling one function after the other then it will finish the first either it may be slow or fast.
I am quiet new to javascript, can not understand that why all javascript calls are asynchronous,
for example, we have calling with order like
call_function1;
call_function2:
if function2 is depend on the results of function1, that can not be ensured, because the execution is asynchronous. Is that true ? And why ?
If true, how to ensure they are synchronous.
If this is duplicated question, I am sorry, because it is quiet new for me.
Thanks fo your answer first.
JavaScript calls are synchonous. If second function depends on results of first function, you might use callbacks model.
function foo(callback) {
var results = // get some results;
callback(results);
}
function boo(results) {
// do something with results here..
}
foo(boo);
No Javascript has functions that guarantee order and behave much like other languages. For example:
function f1() {
alert(1);
}
function f2() {
alert(2);
}
f1();
f2();
You will always get 1 and then 2. What's more is AFAIK javascript runs on one thread so you don't have to worry about race conditions either.
The asynchronous part of javascript comes from waiting on events. For example if you make 2 ajax requests (the a in ajax standing for asynchronous is a hint), you cannot guarantee which will come back first and thus if you have different callbacks for the two requests, you can't guarantee which will be called first.
Calling two functions in a row is definitely not asynchronous.
In fact.. javascript is 100% synchronous. Unless you use 'web workers' all javascript will always run in a single thread, in a single process. There is never, ever a situation where 2 scripts are running at the same time.
Even if you handle an event, coming from an XMLHTTPRequest for instance, the event will only be triggered after all other javascript code has stopped executing.
As mentioned in the comments to your question, JavaScript function calls are usually not asynchronous. The following will be executed in order:
function sayHello() {
console.log("Hi");
}
function sayBye() {
console.log("Bye");
}
sayHello();
sayBye();
The above code will first print "Hi", then "Bye", as the calls to sayHello and sayBye are in that order.
However, if a function does perform some action asynchronously, and you have another function that relies on the result of that, you can supply the second function as a callback to the asynchronous request. For example:
xmlHttpRequestObj.onreadystatechange = function() {
if(xmlHttpRequestObj.readyState == 4 && xmlHttpRequestObj.status == 200) {
//Asynchronous call returned successfully. Do something that relies on that here.
}
}
I don't know how you say that "Javascript is generally said to be asynchronous". It is generally the opposite: Javascript is almost always not asynchronous.
So generally (no ajax, no callback, no event handling), the following functions calls will execute sequentially.
function1();
function2();
If you are assigning both these functions to a single event, both will be called concurrently, but will not be executed in parallel. Same if both are called at the same time (using setTimeout), or as an Ajax callback. See Is JavaScript guaranteed to be single-threaded? for a very good explanation.
You could have heard that Ajax is asynchronous. That is true when you consider the request to servers without interfering with the user, "in the background". But this does not mean that Javascript is asynch. In fact even with Ajax calls, the javascript part is single threaded.
I'm trying to figure the best way to get my functions executing in the correct order.
I have 3 functions
function 1 - squirts OPTIONs into a SELECT via JSON and marks them as selected
function 2 - squirts OPTIONS into a 2nd SELECT and marks them as selected
function 3 - gets the values from the above SELECTs along with some additional INPUT values, does an AJAX GET resulting in JSON data, which is read and populates a table.
With JQuery Onload, I execute:
function1();
function2();
function3();
I'm finding function3 is executing before the SELECTs have been populated with OPTIONS and hence the table has no results, because the values sent in the GET were blank.
I know this is probably a very simple problem and that there are probably a dozen ways to accomplish this, but basically I need the best way to code this so that function3 only runs if function1 and 2 are complete.
I've come into Javascript via the back door having learnt the basics of JQuery first!
Thanks for your assistance.
Javascript executes synchronously, which means that function3 must wait for function2 to complete, which must wait for function1 to complete before executing.
The exception is when you run code that is asynchronous, like a setTimeout, setInterval or an asynchronous AJAX request.
Any subsequent code that relies on the completion of such asynchronous code needs to be called in such a manner that it doesn't execute until the asynchronous code has completed.
In the case of the setTimeout, you could just place the next function call at the end of the function you're passing to the setTimeout.
In the case of an AJAX call, you can place the next function call in a callback that fires upon a completed request.
If you don't want the execution of the subsequent function to occur every time, you can modify your functions to accept a function argument that gets called at the end of the asynchronous code.
Something like:
function function1( fn ) {
setTimeout(function() {
// your code
// Call the function parameter if it exists
if( fn ) {
fn();
}
}, 200);
}
function function2() {
// some code that must wait for function1
}
onload:
// Call function1 and pass function2 as an argument
function1( function2 );
// ...or call function1 without the argument
function1();
// ...or call function2 independently of function1
function2();
I recommend you use a Promises library. You can hack simple solutions like other answers suggest, but as your application grows, you'll find you are doing more and more of these hacks. Promises are intended to solve these kinds of problems when dealing with asynchronous calls.
The CommonJS project has several Promises proposals which you should check out. Here is a question I asked on SO about Promises a while back with links to other solutions. Learn more about Promises in this Douglas Crockford video. The whole video is good, but skip to just past half way for promises.
I'm using the FuturesJS library currently as it suits my needs. But there are advantages to other implementations as well. It allows you to do sequences very easily:
// Initialize Application
Futures.sequence(function (next) {
// First load the UI description document
loadUI(next); // next() is called inside loadUI
})
.then(function(next) {
// Then load all templates specified in the description
loadTemplates(next); // next() is called inside loadTemplates
})
.then(function(next) {
// Then initialize all templates specified in the description
initTemplates();
});
Even more powerful is when you need to join async events together and do another action when all of the other async events have completed. Here's an example (untested) that will load a bunch of HTML files and then perform an action only once ALL of them have completed loading:
var path = "/templates/",
templates = ["one.html","two.html","three.html"],
promises = [];
$.each(templates, function(i,name) {
promises[i] = Futures.promise();
var $container = $("<div>");
$container.load(path+name, function(response,status,xhr) {
promises[i].fullfill();
}
});
Futures.join(promises, {timeout: 10000}) // Fail if promises not completed in 10 seconds
.when(function(p_arr) {
console.log("All templates loaded");
})
.fail(function(p_arr) {
console.log("Error loading templates");
});
This might be overkill for your application. But if the application is growing in complexity, using promises will help you in the long run.
I hope this helps!
invoke function2 inside of function1 and function3 inside of function2.
It's not clear why f1 and f2 are executing before f3.
Also, are you using the preferred $(document).ready() or some variation of onload?
It might be helpful if you provide a reproducible test case.
fun3() will only run after both are ready. It might run twice. You can fix this with a lock inside fun3() you would need a Singleton to guarantee it works correctly.
var select1ready = false, select2ready = false;
fun1()
{
// do stuff
select1ready = true;
fun3();
}
fun2()
{
// do stuff
select2ready = true;
fun3();
}
fun3()
{
if (select1ready && select2ready)
{
}
}
fun1();
fun2();