JQuery - force multiple ajax requests to run in sequence [duplicate] - javascript

This question already has answers here:
Make jQuery ajax calls in order
(2 answers)
Closed 5 years ago.
The following executes each ajax call using jQuery in sequence. The calls must be in sequence. The only way I've found this works is by using async: false, which I know is deprecated and should not be used. The code below loops through each element in the [name] array and fires each ajax request in sequence. When I remove async: false, the ajax calls are made out of sequence and sometimes one of them does not seem to fire at all. I thought ajaxComplete might help me here but I've had no luck. Is there a way to make these ajax calls fire in sequence?
function doGetJson(name1) {
var URL = 'http://some url/?name=' + name1;
$.ajax({
url : URL,
dataType : 'jsonp',
async: false,
jsonpCallback : 'getJson',
name: name1,
index: i,
success : handleJson
});
};
function handleJson(data) {
<...some other operations...>
};
var name = "test1,test2,test3".split(",");
for (var i = 0; i < name.length ; i++ )
{
doGetJson(name[i]);
}

You should make use of promises. First let your function return the $.ajax like so:
function doGetJson(name1) {
var URL = 'http://some url/?name=' + name1;
// notice the return !!!
return $.ajax({
url : URL,
dataType : 'jsonp',
async: false,
jsonpCallback : 'getJson',
name: name1,
index: i,
success : handleJson
});
};
Then you chain them like that:
var name = "test1,test2,test3".split(",");
var promise = name.slice(1)
.reduce( (a,b) => a.then(doGetJson.bind(null, b))
, doGetJson(name[0]) )
promise.then(function(){
// do something when all requests are ready
})

Related

jQuery -- nesting ajax calls and using data from each call - wikipedia API

I am having problems in nesting ajax calls with jQuery to wikipedia api.
The HTML is simple, just an input form and a button:
<input id='search-input' type="text" class="form-control">
<button id="search-button" type="button" class="btn btn-primary">Search</button>
<div id ='outputDiv'></div>
THe search button has an event listener that fires a function that grabs data from wikipedia API:
...
searchBtn.addEventListener('click', searchwiki);
...
function searchwiki(){
let searchTermObjects =[]
let term = inputfield.value;
let titleUrl = search_term(term);
createWikiObject(titleUrl).then(function(){
searchTermObjects.forEach(function(elem){
addExtrctToObj(elem)
})
}).then(function(data){
append_result(searchTermObjects)
})
}
function createWikiObject(titleUrl){
return $.ajax({
type: "GET",
url: titleUrl,
dataType : 'jsonp',
async: true,
error : function(ermsg){
console.log('error in searching',ermsg)
},}).then(function(data){
for(let i = 0; i < data[1].length; i ++){
searchTermObjects.push({
'title': data[1][i].replace(/\s+/g, '_'),
'description': data[2][i],
'url': data[3][i],
})
}; // this for loop should push each result as an object to an array named searchtTermObjects, and i am planning to use this array in the next ajax call to add another property named extract to each object in array
}
);
}
function addExtrctToObj(obj){
console.log(obj)
return $.ajax({
type: "GET",
url: get_text(obj['title']),
dataType : 'jsonp',
async: true,
error : function(ermsg){
console.log('error getting text',ermsg)
}
}).then(function (data){
let pageID = Object.keys(data.query.pages);
if(data.query.pages[pageID].hasOwnProperty('extract')){
obj['extract'] = data.query.pages[pageID].extract;
}
// this function adds the extracted text for each article ,
// the searchTermObjects now looks something like:
/ [{'title':...,'url':...,'description':...,'extract':..},{...}]
})
};
function append_result(termsObjectsArray){
// this function should loop through the searchtermobjects and append leading text for each object in the array to the Output div under the button
for (let i = 0; i < termsObjectsArray.length; i++){
let newDiv = document.createElement('div');
HOWEVER, Object.keys(termsObjectsArray[i]) returns only three keys at this time, and doesn't see the extract key'
console.log(Object.keys(termsObjectsArray[i]))
newDiv.classList.add('wiki-result');
newDiv.innerHTML = termsObjectsArray[i]["extract"];
HERE is where i get error -- the inerHtml of newDiv has value UNDEFINED
outputDiv.appendChild(newDiv);
}
}
// the api calls are formed with these functions:
let base_url = "https://en.wikipedia.org/w/api.php";
function search_term(term) {
let request_url = base_url + "?action=opensearch&search=" + term + "&format=json&callback=?";
return request_url;
}
function get_text(term){
let request_url = base_url + "?action=query&prop=extracts&exintro=&format=json&titles=" + term; // explaintex= returns plaintext, if ommited returns html
return request_url;
}
afetr I console.log(searchTermObjects) i get what i need, the array with objects that have all 4 properties with correct names, but I don't understand why the append_result function doesn't see the 'extract' key.
Next to the logged object in the console is the 'i' sign that says 'Value below was evaluated just now' , and there I have what I wanted -- every search result as an object with title, url, description, and extract keys.
copy this code to your IDE to see if you can help me with finding solution.
I believe the issue you're having is that you're attempting to return a Deferred object, and there's nothing to return yet because of the deferral.
return $.ajax({
type: "GET",
url: get_text(obj['title']),
dataType : 'jsonp',
async: true,
error : function(ermsg){
console.log('error getting text',ermsg)
}
})
The async value is true, so the code is moving on before the request is finished, and you're getting a null value back.
Try setting async: false and see if you get a better response. As pointed out by Andrew Lohr in the comments, this is not a good way to solve the problem, it will only tell you if that is the problem.
If it is, then I would recommend not breaking the request up into multiple functions. You should just chain the AJAX calls, using the deferral approach. It would be structured like this:
$.ajax({ ... }).then(function(data){
// ... do something with the data ...
// Make your followup request.
$.ajax({ ... }).then(function(data) {
// ... finalize the response ...
});
});
Also consider using the context option in the ajax call to pass in a callback method that can be fired once the chain is complete.

jquery : constructed data is undefined [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
I spent lot of time to figure this out but did not find anything,
function constructAgenciesData() {
$.ajax({
url: "getAgenciesAndGlobalJson.do",
dataType: "json",
success: function(data){
$.each(data, function (index, row) {
// console.log("data : "+ JSON.stringify(data));
$("#"+row.id).data("assignedAgencies", row.assignedAgencies).data("restOfAgencies", row.restOfAgencies).data("global", row.global).data("globalID", row.globalID);
});
}
});
}
constructAgenciesData();
$(function($){
$(".globalswitch").each(function () {
var idRow = $(this).parents('tr')[0].id;
alert(idRow);
console.log($('#'+idRow).data("global"));// <-- UNDEFINED
$(this).switchButton({
checked: row.data("global")
});
});
$(document).on('click','button.btn', function () {
var idRow = $(this).parents('tr')[0].id;
var title = $(this).parents('td:first').siblings(':eq(1)').text();
title = "Rule Name : " + title;
$("#divPopUp").data('param_1', idRow);
$("#divPopUp").data('opener', this).dialog("option", "title", title).dialog("open");
console.log($('#'+idRow).data("global"));// <-- WORKING
var old_array = $('#'+idRow).data("restOfAgencies");
var new_array = $('#'+idRow).data("assignedAgencies");
addCheckbox(diff(old_array,new_array));
});
});
I don't know why the same line :
console.log($('#'+idRow).data("global"));
is undefined in the .each function.
BUT it is working in the click function .
Your $.ajax call is asynchronous. This means that it is firing request while the rest of the Javascript is being run.
The success function within constructAgenciesData() might not have been completed prior to the IIFE $(function($){.
Therefore, there is no guarantee that the .data('global') will be set by the time you're trying to access it within the $(".globalswitch").each loop.
A solution to this issue would be to wrap the $(".globalswitch").each loop within a function globalSwitchLoop() and fire that on the success of the $.ajax call.
Also, take a look at jQuery's promises.

Array doesn't keep content, maybe something with declaration [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 9 years ago.
I have an array declared in an else structure
var days = new Array();
$.ajax({
url: 'someurl',
dataType: 'jsonp',
success: processJSON
});
I process the data from the ajax call in the processJSON function
function processJSON(jsonData) {
var weather = jsonData.data.weather;
for(var key in weather) {
var day = weather[key];
days.push(new Array(day.tempMaxC, day.type));
}
}
I add some other arrays to the days-array.
If I check it in the console (in the processJSON-function), the length is three/
Then when I want to use the variable in some code under the the ajax-call, nothing works and when I check the length it's 0. I guess it's something with declaration?
Is your code under the Ajax call happening after the processJson function? The call to the ProcessJson function is asynchronous and happens only after the Ajax call finishes. However the code following it might happen before. So it might be a timing thing. If you need the array for any other processing you should have it in the callback or after you know the callback has been finished.
Put the declaration outside of the condition/else
var days = new Array();
if(...){
}else{
$.ajax
}
You need to wait until the XHR call has finished. It looks like you're using JQuery so check out their deferred docs (http://api.jquery.com/deferred.then).
You would end with something like this:
$.ajax({
url: 'someurl',
dataType: 'jsonp'
}).then(function( jsonData ) {
var weather = jsonData.data.weather;
for(var key in weather) {
var day = weather[key];
days.push(new Array(day.tempMaxC, day.type));
}
console.log( 'done!', days );
});

Getting list back from ajax jsonp callback

I am making an ajax call via jquery with a jsonp callback function. The callback gets called and generates a list for me that I need to return to the original alling function and assign to a variable. However, it is not getting passed back. I know I am doing something wrong or misunderstanding how this flow works. Could somebody please point me in the correct direction? Here is the (abbreviated) code:
function() {
..build url...
var multiTargets = getMultiMetrics(url);
...do stuff with list...
}
getMultiMetrics = function(url) {
$.ajax({
url: url,
jsonp : true,
jsonpCallback: 'metricCallback',
cache: true,
dataType : 'jsonp',
async: false
});
};
metricCallback = function(data) {
var items = [];
for (var i = data.length - 1; i >= 0; i--) {
items.push(data[i].target);
};
return items;
};
Try not use quotes in
jsonpCallback: metricCallback,
This parameter must be function instead of a string

jquery ajax gets HTML but will not return it [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to return the response from an AJAX call from a function?
I'm trying to get some HTML content via ajax. But for some reason, though the HTML makes it to the ajax function, when I try to use it as a returned value, I get undefined.
Like this:
function get_additional_options(name) {
var post = $.ajax({
type: 'post',
url: 'order_queries_templates/html/' + name + '_additional_options.php?<?=time()?>',
//data:'product_id=' + product_id,
dataType: 'html'
});
post.done(function (p) {
console.log(p); //prints out all the HTML just as I would expect
return p;
});
}
but when I try to get the HTML to append it to my page like this
if (has_additional_options == "t"){
var html_to_append = get_additional_options(name);
console.log(html_to_append); // undefined
}
It is the same result if I use the done() method, or just return the value as a success callback. What is my error?
You can't return values from asynchronously called functions.
You should return post (i.e. the result of $.ajax) and then register a .done handler outside of your function:
function get_additional_options(name) {
return $.ajax({
...
});
};
if (has_additional_options == "t") {
get_additional_options(name).done(function(p) {
console.log(p);
});
// NB: code execution continues here immediately - don't do anything
// else here - all further stuff must be done in the above callback
}
You are returning the HTML value inside the anonymous function.
You're basically passing it to the post.done method.
Maybe it's better to use events in this case since you're running asynchronous code here.
function get_additional_options(name) {
var post = $.ajax({
type: 'post',
url: 'order_queries_templates/html/' + name + '_additional_options.php?<?=time()?>',
//data:'product_id=' + product_id,
dataType: 'html'
});
post.done(function (p) {
$("body").trigger("html_loaded",[p]);
);
}
$("body").on("html_loaded", function (htmlData) {
// Do something with your HTML data here.
$(this).append(htmlData);
});

Categories