Print content after function ends his work - javascript

here's my problem: I have to print same times after a function has done his work to show differents content in page. I used the promise object to get when the function ends his work.
One print for each loop.
I retrieve the array via json to the elements must be print to print one per time.
The code is here
$('#prev_print').on("click", (function(event) {
$.ajax({
type: 'POST',
url: 'json/get.php?multi=' + $("#prev_id").val(),
dataType: 'json',
encode: true
}).then(function(data) {
if ((data)["success"] === true) {
$.each((data)["multi"], function(i, n) {
prev_edit(n).then(function() {
window.print();
});
});
}
});
}));
function prev_edit(prev_id) {
return $.ajax({
type: 'POST',
url: 'json/get.php?t=2&p=' + prev_id,
dataType: 'json',
encode: true
}).then(function(data) {
var prom;
//some operations to show the retrieved data from json
$('html,body').animate({ scrollTop: $("#cli_header").offset().top }, 'slow');
$("#risultato").show();
prom = $("#preventivo_edit").show("slow").promise();
return prom;
});
};
It prints many times to the lenght of the array but not wait when function finish his work

Related

How can a guarantee one ajax call is complete before calling another?

I am working on a flask application and there is this javascript function associated with a form
function applyQueries() {
// does some things
if(currentCatalog != ''){
addCatalogFilters(currentCatalog);
}
$.ajax({
type: 'POST',
url: "/applyQueries",
contentType: "application/json",
success:function(response){
// does some stuff here
})
}
The addCatalogFilters() function is also an ajax call. Both these calls change some variables in the python side of things. What I want to know is if the first ajax call (in addCatalogFilters), is guaranteed to execute and return before the second one. I am ending up with weird results that appear to be race conditions based on the order the ajax calls execute. Is this possible with code structured like this? Also if so, how can I fix it?
// Add user catalog filters
function addCatalogFilters() {
catalog = currentCatalog;
formData = new FormData(document.getElementById('catalogFilterForm'));
$.ajax({
type: 'POST',
url: "/addCatalogFilters",
data: formData,
processData: false,
contentType: false,
success: function (response){
document.getElementById(catalog + 'close').style.display = 'block';
document.getElementById(catalog + 'check').style.display = 'none';
addBtns = document.getElementsByClassName("addBtn");
removeBtns = document.getElementsByClassName("removeBtn");
for (i = 0; i < addBtns.length; i++) {
addBtns[i].style.display = "none";
removeBtns[i].style.display = "inline-block";
}
}
})
};
You can ensure with success function of ajax. First call a ajax (let's say ajax1) then call another ajax call within the success function of first ajax call (ajax1 success function).
addCatalogFilters(currentCatalog)
{
$.ajax({
type: 'POST',
url: "/the-post-usl",
success:function(response){
$.ajax({
type: 'POST',
url: "/applyQueries",
contentType: "application/json",
success:function(response){
// does some stuff here
});
})
}
function applyQueries() {
// does some things
if(currentCatalog != ''){
addCatalogFilters(currentCatalog);
}
}
It may not be the optimum way. But guarantee one ajax call is complete before calling another.
You could try using async/await like this:
async function applyQueries() {
if(currentCatalog !== ''){
const filtersAdded = await addCatalogFilters(currentCatalog);
}
// Perform AJAX call
}
By usinc async/await, your code will wait until the addCatalogFilters() function has resolved. However, for this to work, the addCatalogFilters() function should be async with a return value. Something like this:
async function addCatalogFilters(catalog){
// Ajax call
$.ajax({
type: 'POST',
url: "foo",
contentType: "application/json",
success:function(response){
return true
})
}
Depending on how applyQueries is called, you may need to have an await or .then where you call it. Note that you can also use "result = await addCatalogFilters(currentCatalog)" to put the ajax result into a variable result that you can work with and pass to your $.ajax call in applyQueries. I don't know the nature of your code, so I can't make any direct suggestions.
async function applyQueries() {
// does some things
if(currentCatalog != ''){
// await on the returned Promise-like jqXHR (wait for ajax request to finish)
// recommend assigning awaited result to a variable and passing to next $.ajax
await addCatalogFilters(currentCatalog);
}
return $.ajax({
type: 'POST',
url: "/applyQueries",
contentType: "application/json",
success:function(response){
// does some stuff here
})
}
// Add user catalog filters
function addCatalogFilters() {
catalog = currentCatalog;
formData = new FormData(document.getElementById('catalogFilterForm'));
// return the Promise-like jqXHR object: https://api.jquery.com/jQuery.ajax/#jqXHR
return $.ajax({
type: 'POST',
url: "/addCatalogFilters",
data: formData,
processData: false,
contentType: false,
success: function (response){
document.getElementById(catalog + 'close').style.display = 'block';
document.getElementById(catalog + 'check').style.display = 'none';
addBtns = document.getElementsByClassName("addBtn");
removeBtns = document.getElementsByClassName("removeBtn");
for (i = 0; i < addBtns.length; i++) {
addBtns[i].style.display = "none";
removeBtns[i].style.display = "inline-block";
}
}
})
};
You can use async/await. However, as no one has mentioned, I would like to demonstrate how you can accomplish this with Promise.
Lets define two functions:
function first_function(data) {
return new Promise((resolve, reject) => {
let dataSet = [[]];
let response;
$.ajax({
type: "POST",
url: 'example.com/xyz',
async: false,
data: data,
success: function (value) {
response = value;
dataSet = JSON.parse(response);
resolve(dataSet)
},
error: function (error) {
reject(error)
},
processData: false,
contentType: false
});
})
}
function second_function(data) {
return new Promise((resolve, reject) => {
let dataSet = [[]];
let response;
$.ajax({
type: "POST",
url: 'example.com/abc',
async: false,
data: data,
success: function (value) {
response = value;
dataSet = JSON.parse(response);
resolve(dataSet)
},
error: function (error) {
reject(error)
},
processData: false,
contentType: false
});
})
}
Now you can make sure that second_function() gets called only after the execution of ajax request in first_function() by following approach:
first_function(data)
.then(dataSet => {
//do other things
second_function(dataSet)
.then(dataSet2 => {
////do whatever you like with dataSet2
})
.catch(error => {
console.log(error);
});
});

how to optimize two ajax call in single page?

i have two ajax call in my script. one is working other is not. but both are working individual. they are not nested and there is no dependicy on each other.
only first ajax call is working second one is not.
my script is:
$('textarea').mentiony_user({ //#
onDataRequest: function (mode, keyword, onDataRequestCompleteCallback) {
$.ajax({
url: "search_user_list.php",
method: "post",
data: {keyword: keyword},
dataType: "json",
success: function (response) {
var data = response;
// console.log(data);
data = jQuery.grep(data, function( item ) {
return item.name.toLowerCase().indexOf(keyword.toLowerCase()) > -1;
});
onDataRequestCompleteCallback.call(this, data);
// setTimeout(data, 1000);
}
});
},
timeOut: 500, // Timeout to show mention after press #
});
// item list
$('textarea').mentiony_item({ //#
onDataRequest: function (mode, keyword, onDataRequestCompleteCallback) {
$.ajax({
url: "search_item_list.php",
method: "post",
data: {keyword: keyword},
dataType: "json",
success: function (response) {
var data = response;
console.log(data);
data = jQuery.grep(data, function( item ) {
return item.name.toLowerCase().indexOf(keyword.toLowerCase()) > -1;
});
onDataRequestCompleteCallback.call(this, data);
// setTimeout(data, 1000);
}
});
},
timeOut: 500, // Timeout to show mention after press #
});
</script>

Multiple AJAX calls without blocking

I run a function called checker every 60 seconds like so:
setInterval( checker, 60 * 1000 );
checker has an array of URLs which it checks via AJAX, the current code is like this:
$.ajax({
url: sites[i].url,
type: "GET",
dataType: "json",
async: false,
success: function(data){
//blah blah blah
}else{
//something else
},
error: function(){
//blah blah blah
}
});
The code works, changes some UI based stuff depending on the results of the JSON. My problem is that the execution time for this checking several sites is ~4 seconds, at which point the page becomes unresponsive for this time. If I remove async: false the code no longer works as expected.
Someone mentioned using callbacks to solve the problem but don't understand how to use them in this context.
EDIT
Updated code based upon suggestion from adosan:
function promtest(){
var sites = [
{ name: "WorkingSite", url: "http://sitename.com/testing.php" },
//a bunch more sites, 1 returns a 404 to test for failure
{ name: "404Site", url: "http://404url.com/testing.php" }
];
var promiseList = [];
for(var i in sites){
var promise = $.ajax({
url: sites[i].url,
type: "GET",
dataType: "json",
async: true,
success: function(data){
if( data.Response != 'OK' ){
console.log('Site ' + sites[i].name + ' Not OK' );
}else{
console.log( 'Site ' + sites[i].name + ' OK ');
}
},
failure: function(data){
console.log('Failure for site: ' + sites[i].name);
},
error: function(){
console.log('Site ' + sites[i].name + ' Not OK' );
}
});
promiseList.push(promise);
}
$.when.apply($, promiseList).then(function(){console.log('success')}, function(){console.log('fail')});
}
In the console I see:
Site 404Site Not OK
Site 404Site Not OK
Site 404Site Not OK
Site 404Site Not OK
Site 404Site Not OK
Site 404Site Not OK
Site 404Site Not OK
fail
Site 404Site Not OK
Site 404Site Not OK
Site 404Site Not OK
Site 404Site Not OK
Note that the site name is always showing as the last one on the list.
You may use Promise (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise) here. Example:
function checker(url) {
return new window.Promise(function (resolve, reject) {
function successCallback(response) {
resolve(response);
}
function errorCallback(response) {
reject(response);
}
$.ajax({
data: data,
dataType: 'JSON',
type: 'GET',
url: url
})
.done(successCallback)
.fail(errorCallback);
});
}
function checkerSuccess(response) {
console.log(response);
}
function checkerError(error) {
console.warn(error);
}
checker('http://api.example.com').then(checkerSuccess).catch(checkerError);
You can use jQuery built in deferred mechanism (a promise).
https://api.jquery.com/category/deferred-object/
jQuery.ajax function does return a promise object which can be asigned to a variable.
https://api.jquery.com/jQuery.ajax/
var promise = $.ajax({
url: sites[i].url,
type: "GET",
dataType: "json",
async: true
});
The nice thing about promises is that you can combine multiple promisses into bigger one.
var promiseList = [];
promiseList.push(promise);
$.when.apply($, promiseList).then(function(){/*SUCCESS*/}, function(){/*FAILURE*/});
Complete code should look like so:
var promiseList = [];
for(var i in sites){
var promise = $.ajax({
url: sites[i].url,
type: "GET",
dataType: "json",
async: true
});
promiseList.push(promise);
}
$.when.apply($, promiseList).then(function(){/*SUCCESS*/}, function(){/*FAILURE*/});
I would try this one.
Let's say that the object that you want to be updated is the var foo:
var foo = "";
$.ajax({
url: sites[i].url,
type: "GET",
dataType: "json",
async: false,
success: function(data){
foo = data.gottenValue1
}else{
//something else
},
error: function(){
//blah blah blah
}
});

How can I make sure that other functions is run after this get function is fully completed and rendered?

I have this script that adds elements with data by a get json function.
$(document).ready(function() {
ADD.Listitem.get();
});
It basicly adds a bunch of html tags with data etc. The problem I have is following:
$(document).ready(function() {
ADD.Listitem.get();
var arr = [];
$(".Listitem-section-item-title").each(function() {
arr.push($(this.text()));
});
});
-
get: function(web) {
AST.Utils.JSON.get("/_vti_bin/AST/ListItem/ListitemService.svc/GetListItem", null, AST.Listitem.renderListitem);
},
renderListitem: function(data) {
$("#Listitem-template").tmpl(data["ListItemResults"]).prependTo(".ListItem-section-template");
}
and here is the json get:
ADD.Utils.JSON.get = function (url, data, onSuccess) {
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
async: true,
url: url,
data: data,
cache: false,
dataType: "json",
success: onSuccess,
error: ADD.Utils.JSON.error,
converters: { "text json": ADD.Utils.JSON.deserialize }
});
}
The array each loop is not running beacuse the get method is not finished with rendering the Listitem-section-item-title selector so it cant find the selector.
Is there any good solutions for this?
You could change your functions to return the promise given by $.ajax :
ADD.Utils.JSON.get = function (url, data) {
return $.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
async: true,
url: url,
data: data,
cache: false,
dataType: "json",
converters: { "text json": ADD.Utils.JSON.deserialize }
}).fail(ADD.Utils.JSON.error);
}
get: function(web) {
return AST.Utils.JSON.get("/_vti_bin/AST/ListItem/ListitemService.svc/GetListItem", null).done(AST.Listitem.renderListitem);
},
So that you can do
$(document).ready(function() {
ADD.Listitems.get().done(function(){
var arr = [];
$(".Listitem-section-item-title").each(function() {
arr.push($(this.text()));
});
});
});
Callback:
$(document).ready(function() {
ADD.Listitem.get(url,data,function(){
var arr = [];
$(".Listitem-section-item-title").each(function() {
arr.push($(this.text()));
});
});
});
Without callback:
If you cant get the get method to take a callback or return a promise then I think the best way will be to check when its done.
$(document).ready(function() {
ADD.Listitem.get();
var timer = setInterval(function(){
if ($("#thingWhichShouldExist").length>0){
var arr = [];
$(".Listitem-section-item-title").each(function() {
arr.push($(this.text()));
});
clearInterval(timer);
}
},50);
});
Retrieve the values and on success, call a function which will push the values into the array.
Also, arr.push($(this.text())); should be arr.push($(this).text());.

JQuery Ajax call, return value problem

function getMore(from){
var initData = "&start-index=";
initData += from;
$.ajax({
type:"POST",
url: '', //removed the URL
data: initData,
dataType: 'json',
success: function(result) {
return result;
},
error: function(errorThrown) {
}
});
return result;
}
Its a google base query; I have another function that makes the initial server call and gets the first 250 items. I then have a running counter and as long as the results = 250 it calls the server again, but starting at "start-index=" of the current amount of items pulled off. This part all works correctly and with firebug I can also see that the server response is proper JSON.
The trouble I'm having is trying to return the JSON from this function to the function that called it. I do not want to call the original function again because it will clear the arrays of data already pulled from the server. Each time it returns to the parent function it's null.
Does anyone know how i can go about returning the data using "return"?
function FuncionCallGetMore(){
//...
getMore('x-value', FuncionGetReturn);
//...
}
function FuncionGetReturn(error, value){
if (!error) {
// work value
}
}
function getMore(from, fn){
var initData = "&start-index=" + from;
$.ajax({
type:"POST",
url: '', //removed the URL
data: initData,
dataType: 'json',
success: function(result) {
fn(false, result);
},
error: function(errorThrown) {
fn(true);
}
});
return;
}
The only way that you can do what you're describing is to make the AJAX call synchronous, which you don't want to do since it will lock the UI thread while the request is being made, and the browser may will to freeze. No one likes freezing.
What you want to do is use callbacks. Post the code of the other functions involved so I can get a better idea of what is going on. But basically, what you want to do is to create an asynchronous loop.
function listBuilder() {
var onError = function(response) {
// ...
};
var onSuccess = function(response) {
// Handle the items returned here
// There are more items to be had, get them and repeat
if ( response.length == 250 ) {
getMore(onSuccess, onError, 250);
}
};
getInitialSet(onSuccess, onError);
}
function getMore(onSuccess, onError, from) {
$.ajax({
type:"POST",
url: '', //removed the URL
data: "&start-index=" + from,
dataType: 'json',
success: onSuccess,
error: onError
});
}

Categories

Resources