javascript async woes - javascript

This is a newbie JavaScript question, but something I'm not quite sure how to google for help because I'm not sure how to describe the problem in an easy way.
I have a large, somewhat complex JSON that I need to manipulate so that I could reshape the JSON in a way that I get a list of only countries, cities, and sales.
The JSON itself isn't the issue for me, it's what I would like to do with it once I've received it. Basically, I'd like to create 3 separate objects/arrays from a large received JSON and have those 3 separate objects/arrays accessible for usage OUTSIDE of the $.ajax call. Yes, I think I could do all of this inside of the $.ajax success callback, but I'd rather have all the JSON processing done elsewhere. My pseudo JavaScript looks something like this:
var model = {
countries: [],
cities: [],
sales: [],
set: function(data) {
//manipulate data here so that model.countries, model.cities, model.sales are populated
}
};
$.ajax({
url: 'example.com/sample.json',
success: function(data) {
model.set(data); //is this the right way to do this?
}
});
$('#countries').html(model.countries);
$('#cities').html(model.cities);
$('#sales').html(model.sales);​
But because JavaScript executes asynchronously, the last 3 lines are always blank because the JSON hasn't been received yet.
So I guess my question is, how do I bind the results of my received JSON to a variable outside of the $.ajax scope so that I could use it wherever on the page?

The simple solution is this:
$.ajax({
url: 'example.com/sample.json',
success: function(data) {
model.set(data);
$('#countries').html(model.countries);
$('#cities').html(model.cities);
$('#sales').html(model.sales);​
}
});
If you want something more frameworky, then you could look at a something like Backbone.js.

Populate your HTML (i.e. update your view) in the AJAX success callback. i.e.
function updateView() {
$('#countries').html(model.countries);
$('#cities').html(model.cities);
$('#sales').html(model.sales);​
}
$.ajax({
url: 'example.com/sample.json',
success: function(data) {
model.set(data); //is this the right way to do this?
updateView();
}
});

Just put those 3 line in the success callback (you can also separate it into a function) and skip the model population.
There are frameworks that allow you to bind DOM elements to JS objects and their data, bu in this case it might be an overkill.

Related

using d3.queue to wait for AJAX response

TL;DR: Any good examples of using AJAX, d3 and PHP to get data from a database and produce graphs from it would be greatly appreciated.
So I'm using d3 to create a force chart based on data pulled from a database using AJAX and PHP, I think there's a few ways to do this, either binding the data to a DOM element, or using D3.queue seem to be the most logical ways to do it, but I'm struggling to find simple examples of using all these bits together.
So my working AJAX request looks like this:
$(document).ready(function() {
$('select[name="locations"]').change(function(){
var location = $(this).val();
$.ajax({
type: 'POST',
url: 'dataselect.php',
data: { l_id: location },
success: function (response) {
console.log(response);
},
});
});
});
I've tried passing the JSON to a DOM element, but no luck extracting it and some people seem to dislike this approach.
The d3 that works looks like this:
d3.json("test.php", function(error, graph) {
if (error) throw error;... Lots more d3 that I don't think is relevant.
test.php and dataselect.php are identical except dataselect has a variable for the AJAX request and the d3 doesn't like it as it is.
So, my question is what is the smoothest way for d3 to "wait" for the data from the AJAX request before running?
I'm guessing I need to wrap some stuff in functions and queue it into some kind of order, but I'm really struggling to tie it together.
Finally, sorry I feel like this should be fairly trivial, but I have read a lot of questions and haven't managed to implement any solutions so far.
EDIT: So following the d3.request route, I've figured out how to send the data without AJAX:
d3.selectAll("#onploc")
.on('change', function() {
var location = eval(d3.select(this).property('value'));
console.log(location);//gets value property of selected menu item.
d3.json("dataselect.php?l_id="+location,function(error, data) {
console.log(data);//sends location variable to php to get data back.
})
});
This could go either way - you could either call the d3 drawing code from your success callback, e.g.
...
success: function(response) {
var data = JSON.parse(response) // maybe, if you need to convert to JSON
d3RenderFunction(data);
}
or you could pass the parameters using d3.request:
d3.request('dataselect.php')
.mimeType("application/json")
.response(function(xhr) { return JSON.parse(xhr.responseText); })
.post({ l_id: location }, function(error, graph) { ... })

ajax call won't execute synchronously

I have built a weather website that calls the flickr API 1st, then calls the yahoo API for the weather. The problem is that the data from the ajax call - from the yahoo API is not here in time for the page to load its content.
Some of the things I have used to try and slow the ajax call down:
setTimeout
wrapping the entire function that $.ajax(success: ) calls into another function, wrapping it in setTimeout
taking the callback function out of $.ajax(success: ), and putting into the $.ajax(complete: ) param
taking the data object that $.ajax(success: ) passes in, and copying that to another var, then going outside of ajax call and putting the function that handles the data inside of $.ajaxComplete(), passing new object var
There are more ways that I have tried to go about this, but I have been at it for 3 days and cannot find a solution. Can someone please help me here
Here is a link to the project
My Weather App On codeine.io
function RunCALL(url)
{
var comeBack = $.ajax({
url: url,
async: false,
dataType:"jsonp",
crossDomain: true,
method: 'POST',
statusCode: {
404: function() {console.log("-4-4-4-4 WE GOT 404!");},
200: function() {console.log("-2-2-2-2 WE GOT 200!");}},
success: function(data){
weatherAndFlickrReport(data);},
error: function(e) {console.log(e);}
});
}
Are you using jQuery? If so, you have to chain your callbacks. Which, at a high level, would looks something like:
//You might want to use .get or .getJSON, it's up to what response you're expecting...
$.getJSON('https://example.com/api/flickr', function(response) {
//This your callback. The URL would end up being https://example.com/api/yahoo/?criteria=lalalalala
$.getJSON('https://example.com/api/yahoo/', { criteria: response.propertyYouWant}, function(yahooResponse) {
//Do something with your response here.
});
});
Edit: I have updated your snippet with a working solution (based on the above AJAX requests) which now shows both your JSON objects ready for consuming. Looky here.

How to get a JSON string result from a database for later use

I am working on the backend for a webpage that displays EPG information for TV channels from a SQlite3 database. The data is provided by a PHP script echoing a JSON string. This itself works, executing the php program manually creates a JSON string of this format
[{"id":"0001","name":"RTL","frequency":"626000000"},{"id":...
I want to use these objects later to create HTML elements but the ajax function to get the string doesn't work. I have looked at multiple examples and tutorials but they all seemed to be focused more on having PHP return self contained HTML elements. The relevant js on my page is this:
var channelList;
$(document).ready(function() {
$.ajax({
url: 'channellookup.php',
dataType: "json",
success: function(data) {
console.log(data.success);
channelList = data;
}
});
});
However the channelList variable remains empty when inspected via console.
What am I doing wrong?
Please ensure that your PHP echoing the correct type of content.
To echo the JSON, please add the content-type in response header.
<?php
header(‘Content-type:text/json’); // To ensure output json type.
echo $your_json;
?>
It's because the variable is empty when the program runs. It is only populated once AJAX runs, and isn't updating the DOM when the variable is updated. You should use a callback and pass in the data from success() and use it where you need to.
Wrap the AJAX call in a function with a callback argument. Something like this:
function getChannels(callback){
$.ajax({
url: 'channellookup.php',
dataType: "json",
success: function(data) {
console.log(data);
if (typeof(callback) === 'function') {
callback(data);
}
},
error: function(data) {
if (typeof(callback) === 'function') {
callback(data);
}
}
});
}
Then use it when it becomes available. You should also use error() to help debug and it will quickly tell you if the error is on the client or server. This is slightly verbose because I'm checking to make sure callback is a function, but it's good practice to always check and fail gracefully.
getChannels(function(channels){
$('.channelDiv').html(channels.name);
$('.channelDiv2').html(channels.someOtherProperty);
});
I didn't test this, but this is how the flow should go. This SO post may be helpful.
EDIT: This is why frameworks like Angular are great, because you can quickly set watchers that will handle updating for you.

jQuery AJAX inside another AJAX call. Sync and finished issues

I get a list of users with an AJAX call, but within the AJAX I call another AJAX to get some information that I could not get with the first AJAX call.
This is basically the structure I'm using, I've removed some unneccesary code that would just clutter, it is possible that there is some syntax errors here and there.
But the code basically works but there are some issues.
function doAJAX(){
$(".loading").show();
$("#table").hide();
$.ajax({
type: "POST",
url: "#Url.Action("Action", "Controller")",
data: { variable: varVariable},
dataType: "json",
success: function (data) {
$.each(data, function (index, value) {
$.ajax({
type: "POST",
url: "#Url.Action("Action", "Controller")",
data: { variable: value.id},
success: function (data2) {
$.each(data2, function (index2, value2) {
$("#tableBody").append("<tr><td>" + value.test +"</td><td>" + value2.test +"</td></tr>");
});
}
});
});
}
});
}
I hide my table at the start, when the AJAX is complete I want to show it again. Where exactly should I place it? Even if I place it at the end of the first AJAX success function it does not work because it gets executed while the other AJAX is still running.
For some reason my list ends up in an odd order everytime the AJAX runs, my list is sorted by alphabetical order yet with this AJAX it ends up random everytime, sometimes the user Adam is at the start, sometimes in the middle and so on. The list itself is fine and in correct order
I do a lot of mathematics that is probably slowing down the second AJAX call which is probably why it ends up in a weird order
Both of these issues are happening because the two AJAXs aren't running "together" but individually, is there a way to make them sync with each other and is there a good way to be sure that the AJAX is completed and now I can show my table?
Sending ajax request inside a loop doesn't seem like a good idea. Why won't you send one ajax request with array of id's as a data, inside your serverside script just get "WHERE id IN (id_list)" array of user records and return them as json-encoded object, and then output it inside a double loop, first for <tr>, second for a list of fields.
I'm sorry i can't provide code, as i don't know what is being returned from your requests to server.

Using Javascript / JQuery to access an array built from an external XML file

I hope this is not too much of a newbe question but I've been pulling my hair out for a while now so thought I'd give in and ask for my first piece of advice on here.
I'm trying to read an external xml file using javascript / jQuery / ajax and place the retrieved data into an array so that I can then reference it later.
So far I seem to be doing everything right upto the point I put the data into the array but then I'm struggling to to read the data anywhere other than inside the function where I create it. Why am I not able to access the Array from anywhere other than in that function?
Here is my code...
Please help!!
$.ajax({
type: "GET",
url: "data.xml",
dataType: "xml",
success: do_xmlParser
});
function do_xmlParser(xml)
{
var myArray = new Array();
$(xml).find("tag").each(function ()
{
myArray.push($(this).find("innerTag").text());
});
console.log("inside "+myArray); // This outputs the array I am expecting
return myArray; // is this right???
}
console.log("outside: "+myArray); // This does NOT output the array but instead I get "myArray is not defined"
You're defining do_xmlParser as a callback to an asynchronous function (success of the jquery ajax call). Anything you want to happen after the ajax call succeeds has to occur within that callback function, or you have to chain functions from the success callback.
The way you have it now, the actual execution of code will go:
ajax -> file being requested -> console.log ->
file transfer done -> success handler
If you're doing some critical stuff and you want the call be to synchronous, you can supply the
async : false
setting to the ajax call. Then, you should be able to do something like this:
var myArray = [],
do_xmlParser = function (xml)
{
$(xml).find("tag").each(function ()
{
myArray.push($(this).find("innerTag").text());
});
};
$.ajax({
type: "GET",
url: "data.xml",
dataType: "xml",
success: do_xmlParser,
async: false
});
console.log("outside: " + myArray);
The async option doesn't work for cross-domain requests, though.
NOTE
I don't recommend doing this. AJAX calls are supposed to be asynchronous, and I always use the success callback to perform all of the processing on the returned data.
Edit:
Also, if you're into reading... I'd recommend jQuery Pocket Reference and JavaScript: The Definitive Guide (both by David Flanagan).
look close and you will see. You are actually firing up an array that dosen't exist. You have declared myArray inside function. Try do something like this.
console.lod("outside :"+do_xmlParser(xml)); // I think that when you merge a string and an array it will output only string, but I can be wrong.

Categories

Resources