jQuery AJAX and JSON Performance Query - javascript

I am storing some JSON data in a text file to query using jQuery Ajax in my page. Currently, my text file contains around 10 facets of data (which could contain an additional 30 facets of data). The JSON data contains a questions and answers to those questions.
In my JavaScript files, I have setup different functions to get specific bits of data.
For example:
function GetAnswer(questionName) {
var correctAnswer = null;
jQuery.ajax({
type: "GET",
url: "../content/questions.txt",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: "",
async: false,
success: function (result) {
$.each(result, function (i, q) {
if (q.questionID == questionName) {
correctAnswer = q.correctAnswer;
return false;
}
});
},
error: function () { },
complete: function () { }
});
return correctAnswer ;
}
As you can see from my code-snippet, I am looping through my JSON to get the data I need. I have other functions coded in a similar fashion to get the question type, question name etc.
What I am finding is that I am calling these functions one after another to get the data I need. I think the way I am querying my JSON data is not good from a performance point-of-view since I am looping through the whole of my JSON dataset until I find a match.
Is there a better way to query my JSON data?
NOTE: I am having to use a text file to store questions due to restrictions of the technology I am using (SCORM 1.2).

Looping through your JSON object is relatively quick. What is slow (comparatively) is loading in that text file each time (though it may be cached).
Either way, I would suggest loading in the JSON either the first time the user initiates a question/answer situation, or just load it in on page load (you can do it asynchronously) and store it for later use.
Example of the latter:
jQuery(document).ready(function(){
var questions = '';
jQuery.ajax({
type: "GET",
url: "../content/questions.txt",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: "",
async: false,
success: function (result) {
questions = result;
},
error: function () { },
complete: function () { }
});
function GetAnswer(questionName) {
var correctAnswer = null;
$.each(questions, function (i, q) {
if (q.questionID == questionName) {
correctAnswer = q.correctAnswer;
return false;
}
});
return correctAnswer ;
}
});

The problem is that you have async set to false. This is bad. This halts the browser while it waits for your requests, and will cause the performance to feel very laggy.

Why not change the structure of your Q&A object to include an id for each question, and make the id an attribute in the object? Then you could pass the id to GetAnswer() and just have it go directly to the right question by referencing the correct attribute? The object could look like this:
{"myQuiz" :
"Q1" :
{ "q" : "What color was George Washington's white horse?",
"a" : "White"
},
"Q2" :
{ "q" : "In what city would you find the Leaning Tower of Pisa?",
"a" : "Pisa"
}
}
If this is assigned to result, and an id of Q2 was passed to GetAnswer(id), you could easily return result.myQuiz[id].a;
As an alternative, if the order of the questions is consistent, you could use an object that contains an array of q and a pairs, and refer to them by index rather than id.

Why not move the logic to a server-side script like PHP that can take in POST parameters and perform the queries against the JSON set and return only the record(s) you wish to receive. Or, if you are intent on keeping this in all js, you could simply store the JSON (as long as it is non-sensitive data) in a local variable and query against it locally.

You could make somekind of mechanism on the server to load data. Then you could send parameters like QuestionName and filter data. This will lower payload sent on the wire.

Related

Using ajax to pass pass values to controller from view in MVC

I have the following in my Razor view file:
<button onClick="getFavouriteBooks()">Display Favourites</button>
<script>
function getFavouriteBooks() {
var ids = JSON.parse(localStorage.getItem("bookIds"));
$.ajax({
type: "POST",
url: '#Url.Action("Favourites", "Home")',
data: ids,
dataType: "javascript"
});
}
</script>
And in my Home Controller, this action:
public async Task<ViewResult> Favourites(string[] ids)
{
// var bookList = code that retrieves list of all books
var favouriteBooks = bookList.Any(book => ids.Contains(book.Id));
return View("Index", favouriteBooks);
}
When user clicks 'Display Favourites' I get a 500 error for localhost/Home/Favourites. Can anyone help me see where I've gone wrong here?
Update: bookIds is an array of string Ids.
Update data with added contentType in ajax call as below and check again
function getFavouriteBooks() {
var ids = JSON.parse(localStorage.getItem("bookIds"));
$.ajax({
type: "POST",
url: '#Url.Action("Favourites", "Home")',
// jQuery refers below mentioned contentType to serialize data in JSON format
// Without this, serialization will be url encoded string
contentType: "application/json; charset=utf-8",
// Assuming ids as a array of strings
// data to be an object that holds Action methods parameters as it's properties
// Stringify object before assigning to data
data: JSON.stringify({
ids: ids
}),
dataType: "javascript"
});
}
So I think there is a couple of things going on here.
I am assuming it’s a “get” request not a “post” request. Since you want to display the books. If you want to “get” all that match an id the easiest way would be to get the total response and loop through it. If it is just for a small project if it’s serious you want to want to change your SQL to find where ID.
But assuming you just want assistance with the JavaScript.
First of all if you put your javascript in line like that you need to also handle the response in line which isn't going to be syntactically very friendly. After all we are not writing php.
The second point about async functions is that you need a response which will happen asynchronously so need to await. Also need to handle the promise
I have simplified what I think is the solution here to use fetch instead of ajax to avoid all the jquery and Ajax setup with code pen but the logic should be there for you to follow up.
https://codepen.io/sijbc/pen/qBRrgBG?editors=1111
fetch('https://api.github.com/users')
.then(res => res.json())//response type
.then(data => console.log(data))
Also found this article which would be worth checking out
https://medium.com/front-end-weekly/ajax-async-callback-promise-e98f8074ebd7

Fetch data from a complex JSON

I'm new to javascript and JSON and I've been given a task to complete. Please find the JSON in the following link,
http://pastebin.com/0BY3eptF
According to me the above is a very complex JSON.
I'm trying to fetch the out from a WSDL via ajax
success: function(api) {
console.log(api.SearchResult); // trying to fetch information on SearchResult object
}
This doesn't work. I would like to learn how to iterate each JSON string loop. I also see an array which is WSResult[]. A neat javascript with explanation will help me a lot. Thank you.
Some web services return content type as plain text instead of json, you have to manually convert into json. below code will help you do the same.
success: function(api) {
if (api.constructor === String) {
api = JSON.parse(api);
}
console.log(api.SearchResult);
}
To loop through api.SearchResult.Result.WSResult array, please find below code
$(api.SearchResult.Result.WSResult).each(function (index, val) {
// here val is single object of WSResult array
});
success: function(api) {}, here, api is still a string, you have to parse it to JSON first:
success: function(api) {
var api = JSON.parse(api);
console.log(api.SearchResult); // trying to fetch information on SearchResult object
}
Not a complete answer, but some useful pointers:
$ajax({
url: 'http://myURL',
// specify the datatype; I think it overrides inferring it from the document MIME type
dataType: 'json',
success: function (api) {
// provided your data does come back as a JSON document
// you should be able to access api.SearchResult
},
error: function( jsXHR, textStatus, errorThrown) {
// always have an error handler, so you can see how it went wrong.
}
);
Read the section on dataType here, as it may solve your problem

How to pass javascript variable to php using ajax

I am trying to pass a javascript variable which I get when a button is clicked to php and then run a mysql query. My code:
function ajaxCall(nodeID) {
$.ajax({
type: "POST",
url: "tree.php",
data: {activeNodeID : nodeID},
success: function(data) {
alert("Success!");
}
}
);
}
function onButtonClick(e, data) {
switch (data.name) {
case "add":
break;
case "edit":
break;
case "delete":
nodeid = data.context.id;
ajaxCall(nodeid);
//query
break;
}
}
<?php
if (isset($_POST['activeNodeID'])) {
$nodeid = $_POST['activeNodeID'];
}
else {
$nodeid = 0;
}
?>
I haven't done this before, so I am not sure why this doesn't work. Any suggestions?
EDIT: Maybe I haven't explained myself well enough. I realise that php is server side and javascript is client side. I have an org chart that is displayed using javascript based on all the info is saved in my db. What I need to do is: when one of the javascript buttons is clicked (edit, delete, add) get the ID of the active node and use it as variable in php to run query. For example, delete the row in the db. What's the best way to do it?
There's a bit of confusion here, the success value stores a callback that gets called when the Ajax call is successful. To give you a simple example, let's say you have an Ajax call like this:
function ajaxCall(nodeID) {
$.ajax({
type: "POST",
url: "tree.php",
data: {activeNodeID : nodeID},
success: function(data) {
console.log(data.my_message);
}
});
This calls a PHP page called tree.php. In this page you do some computation and then return a value, in this case as JSON. So the page looks like this (note that I'm keeping it simple, you should validate input values, always):
$v = $_REQUEST['activeNodeID'];
$to_return = "the value sent is: " . $v;
return json_encode(array('my_message' => $to_return));
This simple PHP page returns that string as a JSON. In your javascript, in the specified callback (that is success), you get data as an object that contains the PHP's $to_return value. What you have written does not really makes sense since PHP is a server language and cannot be processed from the browser like JavaScript.

I'm not getting response from my jsonp

i have this test json url
This is the link
jQuery.support.cors = true;
window.Getdata = function() {
var request = $.ajax({
type: "POST",
data: "{}",
dataType: 'json',
url: "/gh/gist/response.json/4001105/",
mimeType: "application/json; cherset=utf-8",
success: krywaarde,
failure: givealert
});
function krywaarde(result) {
alert("Name = "+result.fighters[0].name);
alert("Nickname = "+result.fighters[0].nickname);
// this changes the text
document.getElementById("routing").innerHTML = result.fighters[0].name;
}
function givealert(error) {
alert('failed!!' + error);
}
}
$(document).ready(function() {
window.Getdata();
});
​
i have edited my whole questions code
the problem i have now is, it works on JSFiddle, but not in my mobile app.
the onlu changes between the 2 is, the ons on Js Fiddle is called on page load, and my real mobile app the function is called on buttonclick!
here is the jsfiddle :
little jsfiddle
the html where i am calling the function is
<a type=button id="processnames" onclick="window.Getdata();" style="color: White; font-size:large;">test json
This line:
kryrequest(https://raw.github.com/appcelerator/Documentation-Examples/master/HTTPClient/data/json.txt?callback=awe)
… looks like it is trying to pass a string literal to the function. String literals must be surrounded by quote marks.
(this section refers to an earlier version of the question)
Additionally, that URI returns a JSON text, not a JSONP script, so it still won't work if you do fix that.
What's more, even if that response did contain JSON-P, it will wouldn't work because the object has a fighters property, but not a name property. The value of fighters is an array (of objects which have names), but those names are strings, not arrays.
(this section refers to an earlier version of the question)

Iterate on array, calling $.ajax for each element. Return array with all ajax results

I've just started working with JavaScript for non-trivial things, so this is probably straightforward...
What I'm trying to accomplish: iterate on an array of product references, fetch the JSON for each reference, and return an array of all the product information (with a hash-like structure indexed by reference).
What I've tried:
function fetchProductData(references){
var product_data = new Object();
references.forEach(function(ref){
$.ajax({
url: "http://localhost:3000/products/find.js?reference=" + ref,
dataType: "jsonp",
type: "GET",
processData: false,
contentType: "application/json",
success: function(data) {
product_data[ref] = data;
}
});
});
alert('before return: ' + product_data);
return product_data;
};
$(document).ready(function(){
var products = fetchProductData(references);
alert('products : ' + products);
});
Here's what I don't understand: the first time I call alert to display the array contents, the array is empty. However, on the second call, the array is populated with the data I want.
In other words, the "products :" alert displays the data I want in the code above. But if I comment the "before return: " alert, it no longer does. Why is this?
So my question is: how can I have jQuery make several $.ajax call to fetch product information, collect that information in an array, and return that array so I can use it elsewhere in my code?
Also, why is the data in the variable magically accessible after it is referenced in an alert?
The "A" in "AJAX" stands for "asynchronous" :). Your program doesn't wait for the call to complete before going on to the next iteration, meaning you'll probably not get all of your data. Also the alert has the same problem. Operation to concat 'before return:' to the string add just enough time to get some data in the variable. On a faster machine you might find you never get data.
I think you really need to rethink your approach. It's not a good idea to have multiple AJAX requests in a loop. It will greatly increase latency of the page. Pass all your parameters once using JSON, then have your server side script loop through that and return a single response in JSON.
function fetchProductData(references){
// make sure your "references" is a JSON object
$.getJSON('http://server/side/url', {'json':references}, function(product_data) {
// do something with product_data (alert them, put them in an array, etc)
});
}
function fetchProductData(references, cb){
var length = 0;
var product_data = new Object();
references.forEach(function(ref){
length++;
$.ajax({
url: "http://localhost:3000/products/find.js?reference=" + ref,
dataType: "jsonp",
type: "GET",
processData: false,
contentType: "application/json",
success: function(data) {
product_data[ref] = data;
if (++count === length) {
cb(product_data);
}
}
});
});
};
$(document).ready(function(){
var products = fetchProductData(references, function(products) {
alert('products : ' + products);
});
});
Use a callback on your asynchronous operation.
The reason it appears to work with the alert call is because alerting a message gives ajax enough time to populate your array. The return statement is only triggered after you click OK on the alert box giving your code a window of 250ms to populate the array with data.
You are executing you ajax query in async mode. And you want a sync result. Try to add:
async: false
Hope this helps.
your $.ajax call is asynchronous, so what is happening is that the first time you make the call, your javascript makes the call, moves on to the next line (alert) and then loops. You're data hasn't returned at that point yet. What you can do to remedy this is to set the async: false option in your $.ajax call.
This is an asynchronous operation. The only sure way to know when the data is ready is in the callback function: success: function () {...}, which gets called when the data has finally returned. Put your alert in there.

Categories