Making a function wait for done [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
Currently I have a function like this:
a: function (val) {
ajaxcall.done(function() {
console.log("Done");
}
}
I want to write another function which calls a, then wait until a is done (so the stuff inside the .done() executes, then it'll continue with the rest. Something like this:
console.log("beginning");
a("test");
console.log("End");
Would that print out
beginning
done
end
or would it sometimes be
beginning
end
done
depending on if the ajax calls take a long time?

That will always print:
beginning
End
Done
Even if the ajax call is instant, because JavaScript always completes the current execution thread before starting another one.

For the example you provided, it should print the done after the end
To wait for your function to end you can write something like that
a: function(val, done) {
ajaxcall.done(done)
}
//or if you want to do something before declaring it's done
a: function(val, done) {
ajaxcall.done(function() {
console.log('done');
done();
})
}
And afterwards use it like that
console.log("beginning");
a("test", function() {
console.log("End");
});

.done() can accept an array of functions to call
function ajaxcall() {
return new $.Deferred(function(d) {
setTimeout(function() {
d.resolve()
}, Math.random() * 3000)
}).promise()
}
function complete() {
console.log("End")
}
function a(val) {
ajaxcall().done([
function() {
console.log("Done");
},
complete
])
}
a()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Use the built in AJAX callback to call your function on complete.
function loadME() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
//if the data is downloaded and you receive no server errors,
if (xhttp.readyState == 4 && xhttp.status == 200) {
yourcallback();
}
};
xhttp.open("GET", "url for your query goes here", true);
xhttp.send();
}
Or in jQuery:
$.ajax({
url: "your api url here",
}).done(function() {
yourcallback();
});

Related

Wait for ajax done in document.addEventListener('DOMContentLoaded') [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I have an ajax request outside the document.addEventListener('DOMContentLoaded'), and I was wondering if I could wait for the ajax request to be completed inside the EventListener (without async:false).
In other words, donĀ“t fire a function inside the EventListener until the ajax request is fully done.
This is my code:
var a;
$.ajax({
t: "GET",
url: "file.php"
}).done(function(data){
a = data;
});
document.addEventListener('DOMContentLoaded', function() {
//Wait for ajax request to complete
someFunction(a);
});
In most cases you would just put the ajax request inside the handler, but if you really needed to you could use an event emitter.
let eventEmitter = new EventTarget();
let data = null;
function getData() {
// simulate ajax call
setTimeout(function() {
data = "some data"
eventEmitter.dispatchEvent(new Event('complete'))
}, 3000)
}
getData();
document.addEventListener('DOMContentLoaded', function() {
//Wait for ajax request to complete
eventEmitter.addEventListener('complete', function() {
// do something here
console.log("Ajax request finished");
})
});
You can define a function which returns the ajax promise like so:
function myajax(){
return $.ajax({
t: "GET",
url: "file.php"
});
var promise = myajax();
document.addEventListener('DOMContentLoaded', function() {
promise.done(function(data){
//Some action
}

Not able to implement Asynchronous XMLHttpRequest in Javascript in the right way

I am using Async XMLHttpRequest to make an API call. Here's the workflow of my program,
first_function(){
var valueToBeReturned = 0;
makeRequest(myCallback)//function for API call
/*rest of the code*/
console.log("print second");
return valueToBeReturned;
}
function makeRequest(callback){
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "my_url", true);
xhttp.send(null);
xhttp.onload = function() {
if(xhttp.readyState === 4) {
if(xhttp.status === 200) {
response = JSON.parse(xhttp.responseText);
callback(null, response);
}
}
}
}
function myCallback(data){
console.log("print first")
}
Now what happens is every time I run it, the entire code in the first function is executed and then the code in makeRequest is executed. I understand JS is synchronous in nature and everything. But I'm not able to get my work done here, which is fisrt it makes API call, then callback is executed, then the code after makeRequest. What am I doing wrong here?
PS this is not the actual code, just to demonstrate the flow of my program
You need to put callback as a parameter in makeRequest. I'm not sure what that null is there for, though. If you want "print second" to print second, you'll need to execute it after myCallback - maybe insert another callback?
function first_function(){
var valueToBeReturned = 0;
makeRequest(myCallback, restOfTheCode)
function restOfTheCode() {
/*rest of the code*/
console.log("print second");
}
}
function makeRequest(callback1, callback2){
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "my_url", true);
xhttp.send(null);
xhttp.onload = function() {
if(xhttp.readyState === 4 && xhttp.status === 200) {
const response = JSON.parse(xhttp.responseText);
callback1(response);
callback2(response);
}
}
}
function myCallback(data){
console.log("print first");
}
But this whole thing would be a whole lot nicer if you used Fetch and Promises instead:
function makeRequest() {
return fetch('my_url')
.then(response => response.JSON())
}
// consume the request:
makeRequest()
.then(responseJSON => {
// do stuff with the responseJSON
});

Make a function wait/"pause" till another one finishes [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
How do I make a function to continue only after another function which was called by it finished. Something like this :
function FunctionOne() {
//Do something ...
FunctionTwo()
//Rest of the code after two is finished
}
function FunctionTwo() {
//Some code
}
EDIT:
The exact functions are like this :
function FunctionOne() {
//Do something ...
var result;
for (var i = 0 , i < 100 , ++i){
result = FunctionTwo()
}
//Rest of the code after two is finished
console.dir(result); //this here gives me undefined
}
function FunctionTwo() {
$.get("url", function(data)
{
result = data;
console.dir(result); //this gives me the data but the first function is still running and it finishes faster then the data is retured
return result;
}
You have to use jQuery.ajax and set async: false
a simple example:
result = '';
function FunctionTwo() {
jQuery.ajax({
url: 'url',
success: function(data) {
result = data;
console.dir(result);
},
async: false
});
alert(result);
}
This should already do as you request. Unless you specify FunctioTwo to run asynchronously it will block for you.
Edit in response to your edit:
If you want the Ajax call to block then there is no reason to have it as an async call, if you do wish it to remain async then utilize the callback of the ajax call to execute you data handling function instead of placing that code inside the main block.
function FunctionOne() {
//Do something ...
var result;
for (var i = 0 , i < 100 , ++i){
result = AJAXCall(i)
}
}
function HandleAJAXResponse(response,id)
{
console.dir(response)
}
function AJAXCall(id) {
$.get("url",function(data,id){
HandleAJAXResponse(data,id);
});
}

(Javascript) Definitely can't return an array [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I've been watching for a while the questions here in Stack Overflow about returning arrays on JavaScript, but not a single answer works in my code. It always returns 'undefined'.
This is the important part of the code:
function VisualizadorIzquierdo () {
// some stuff here
this.dibujar = function () {
var datos = obtenerDatos(0);
alert(datos); //<--- This always returns 'undefined'
// other stuff here
}
// more stuff here
}
function obtenerDatos(id) {
var xmlhttp = ConstructorXMLHttpRequest();
if(!xmlhttp) alert('Error: No se pudo crear el objeto XMLHttpRequest');
else {
xmlhttp.onreadystatechange = function() {
if(xmlhttp.readyState == 4)
{
alert(xmlhttp.responseText); //<--- This returns '[1,2,3,4]'
return xmlhttp.responseText;
}
}
xmlhttp.open('GET', rutaLector + '?archivo=' + archivos[id], false);
xmlhttp.send(null);
}
}
I'v tried defining the variable datos as a new Array() and new Object(). Also I'm trying returning an Object (like {"arreglo" : [1,2,3,4]}), defining a new Array() and new Object() within obtenerDatos(id) function, changing between syncronic and asyncronic, etc ...
But every time it returns 'undefined' :c
So, How can I definitely return an Array from a function?
Thanks in advanced! :)
the reason why you are getting undefined is because you are calling obtenerDatos() which then calls
xmlhttp.send(null);
xmlhttp.send(null); <-- is an asynchronous call. so you obtenerDatos() function immediately returns after that. and since you don't have a return statement returning anything for obtenerDatos then the variable datos will get nothing or undefined as it is doing right now.
obtenerDatos() don't have a return. The only 'return' in its context is inside another function that is being dynamically declared to the onreadystatechange, but that one doesn't count. Its a delayed event, that will be ran at some other time when the AJAX request is concluded. obtenerDatos() itself isn't returning anything.
What you have to do is set up a callback function that will be called with the AJAX response to process it once the AJAX is done fetching the data.
This other question might explain it better.
Try in jQuery.
function VisualizadorIzquierdo () {
// some stuff here
obtenerDatos(0).done(function (result) {
//var datos = obtenerDatos(0);
alert(result);
// other stuff here
});
// more stuff here
}
function obtenerDatos(id) {
return $.ajax({
url: rutaLector + '?archivo=' + archivos[id],
type: "GET",
success: function (result) { },
error: function () { },
traditional: true
});
}

Function inside jquery returns undefined [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
The function I called inside jquery returns undefined. I checked the function and it returns correct data when I firebugged it.
function addToPlaylist(component_type,add_to_pl_value,pl_list_no)
{
add_to_pl_value_split = add_to_pl_value.split(":");
$.ajax({
type: "POST",
url: "ds/index.php/playlist/check_folder",
data: "component_type="+component_type+"&value="+add_to_pl_value_split[1],
success: function(msg)
{
if(msg == 'not_folder')
{
if(component_type == 'video')
{
rendered_item = render_list_item_video(add_to_pl_value_split[0],add_to_pl_value_split[1],pl_list_no)
}
else if(component_type == 'image')
{
rendered_item = render_list_item_image(add_to_pl_value_split[0],add_to_pl_value_split[1],pl_list_no)
}
}
else
{
//List files from folder
folder_name = add_to_pl_value_split[1].replace(' ','-');
var x = msg; // json
eval('var file='+x);
var rendered_item;
for ( var i in file )
{
//console.log(file[i]);
if(component_type == 'video')
{
rendered_item = render_list_item_video(folder_name+'-'+i,file[i],pl_list_no) + rendered_item;
}
if(component_type == 'image')
{
rendered_item = render_list_item_image(folder_name+'-'+i,file[i],pl_list_no) + rendered_item;
}
}
}
$("#files").html(filebrowser_list); //Reload Playlist
console.log(rendered_item);
return rendered_item;
},
error: function()
{
alert("An error occured while updating. Try again in a while");
}
})
}
$('document').ready(function()
{
addToPlaylist($('#component_type').val(),ui_item,0); //This one returns undefined
});
The function addToPlaylist doesn't return anything. It makes an asynchronous request, which eventually executes a callback function, which returns something. The original addToPlaylist function is long done and returned by the time this happens though, and the callback function returns to nobody.
I.e. the success: function(msg) { } code executes in a different context and at a later time than the surrounding addToPlaylist function.
Try this to see it in action:
function addToPlaylist() {
$.ajax({
...
success : function () {
alert('second'); // comes after 'first'
return null; // returns to nobody in particular
}
});
alert('first'); // comes before 'second'
return 'something'; // can only return here to caller
}
You're making your request via AJAX, which by definition is asynchronous. That means you're returning from the function before the AJAX request completes. In fact, your return statement is meaningless as it returns from the callback function, not your addToPlaylist function.
You have a couple of choices. The first one is better.
First, you can work with the asynchronous nature of the AJAX request and pass a callback into your addToPlaylist method (much like you're passing in the anonymous callback to the ajax function) and have the AJAX callback, call that function instead of doing the return. That way your request completes asynchronously and doesn't lock up your browser while it's going on.
function addToPlaylist(component_type, add_to_pl_value, pl_list_no, cb )
{
...yada yada yada...
$.ajax({
...
success: function(data) {
...
if (cb) {
cb.apply(this, rendered_item );
}
}
});
}
Second, you can add the option aSync: false to the ajax call. This will force the AJAX call to run synchronously (essentially it just loops until the call returns then calls your callback). If you do that, you need to capture a local variable in your addToPlaylist function inside the callback and assign the value(s) to it from the callback. At the end of the addToPlaylist function, return this variable as the result.
function addToPlaylist(component_type, add_to_pl_value, pl_list_no )
{
...yada yada yada...
var result = null;
$.ajax({
aSync: false,
...
success: function(data) {
...
result = rendered_item;
}
});
return rendered_item;
}
I agree with deceze. What you need to do is perform the necessary action(s) for rendered_item in the success function rather than relying on getting something back from addToPlayList().

Categories