Autocomplete search taking too long to retrieve data from server - javascript

I have an AJAX autocomplete search in user control page, which gets called on document.ready. In that we makes an AJAX call to web service which takes the data (which is approx. 90,000) from the database, insert data into cache, returns the data to JavaScript and added to the array.
At first it takes the data from the database and after inserting the data into cache, every time it takes the data from cache. When we type something on textbox it matches the text of textbox with array and displays the list. To get 90,000 items from a stored procedure, it takes 2 sec in local server.
But on live server it takes approx 40 secs to take data from a stored procedure. Also for taking data from cache it takes the same time. How can I reduce the time and increase the performance?
AJAX call:
var locationSearchListData = [];
var termTemplate = "<span class='ui-autocomplete-term'>%s</span>";
var postData = '{cultureId : "DE"}';
// Ajax call to run webservice's methods.
$.ajax({
url: "/asmx/SearchLocations.asmx/GetAutoCompleteSearchLocations",
type: "POST",
data: postData,
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (responseData) {
if (responseData != undefined && responseData != null && responseData.d.length > 0) {
for (i = 0; i < responseData.d.length; i++) {
// Add resopnse data in location search lis, this list is used as a source for autocomplete textbox.
locationSearchListData.push({
label: responseData.d[i].locationData,
latitude: responseData.d[i].latitude,
longitude: responseData.d[i].longitude
});
}
}
Web-service:
[ScriptMethod]
[WebMethod(Description = "Provides instant search suggestions")]
public List<GeoLocationObject> GetAutoCompleteSearchLocations(string cultureId)
{
SqlDatabase database = new SqlDatabase(WebConfigurationManager.ConnectionStrings["MasterDB"].ConnectionString);
string databaseName = WebConfigurationManager.AppSettings["databaseName"];
// Key to identify location search data in cache
string cacheKey = "auto_complete_result";
// List to store locations
List<GeoLocationObject> lstGeolocationObject = new List<GeoLocationObject>();
// If location data is present in cache then return data from cache.
if (Context.Cache[cacheKey] is List<GeoLocationObject>)
{
return Context.Cache[cacheKey] as List<GeoLocationObject>;
}
else // If data is not present in cache, get data from db and add into cache.
{
// Call method GetAutoCompleteSearchLocations of LocationManager to get list of geo location object.
lstGeolocationObject = LocationManager.GetAutoCompleteSearchLocations(database, cultureId);
// Checking if lstGeolocationObject is not null
// If its not null then adding the lstGeolocationObject in the cache
if (lstGeolocationObject.Count > 0)
{
// Add locationdata in cache.
// Removed sqlcache dependency.
Context.Cache.Insert(cacheKey,
lstGeolocationObject,
null,
Cache.NoAbsoluteExpiration,
Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable,
null);
}
// Return geolocation data list
return lstGeolocationObject;
}
} // GetAutoCompleteSearchLocations

The main intention of autocomplete facility is to narrow down the search and bring to front only the nearly matching records to ease the user to select the exact record he wants. Try adding a debounceTime() if possible.
Other options are to fine tune the sql query, implementing the server side paging and checking the page render time in browser.

Sorry for my late reply.
Thanks all for helping me to find out the solution.
We have solved the issue by doing some changes in ajax call. We send the search text as:
// set auto complete textbox
$("#<%= txtOrtOderPlz.ClientID%>").autocomplete({
// Set required minimum length to display autocomplete list.
minLength: 3,
// Set source for textbox, this source is used in autocomplete search.
source: function (request, response) {
// Ajax call to run webservice's methods.
$.ajax({
url: "/asmx/SearchLocations.asmx/GetAutoCompleteSearchLocations",
type: "POST",
data: '{ searchText :\'' + request.term + '\' }',
dataType: "json",
contentType: "application/json; charset=utf-8",
Success: function (responseData) {
response(responseData.d);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
}
});
},
Every time we search anything, it takes the search text and call web services, send the search text to SP, get the data from SP and show in autocomplete search.

Related

formatting json data from api

I'm using api to extract exchange rates in json form right now the result shows like this
"RUB":1,"AED":0.06317,"AFN":1.5074,"ALL":2.0112,"AMD":7.0904,"ANG":0.03079,"AOA":6.9821,"ARS":2.4694,"AUD":0.02624,"AWG":0.03079,"AZN":0.02896,"BAM":0.03457,"BBD":0.0344,"BDT":1.7593,"BGN":0.03457,"BHD":0.006468,"BIF":33.7214,"BMD":0.0172,"BND":0.02457,"BOB":0.1177,"BRL":0.08918,"BSD":0.0172,"BTN":1.3948,"BWP":0.2247,"BYN":0.04456,"BZD":0.0344,"CAD":0.02333,"CDF":33.5622,"CHF":0.01691,"CLP":16.1531,"CNY":0.1225,"COP":74.4278,"CRC":10.7597,"CUP":0.4128,"CVE":1.949,"CZK":0.4341,"DJF":3.0571,"DKK":0.1319,"DOP":0.9116,"DZD":2.3957,"EGP":0.3326,"ERN":0.258,"ETB":0.8631,"EUR":0.01768,"FJD":0.03885,"FKP":0.01562,"FOK":0.1319,"GBP":0.01562,"GEL":0.04833,"GGP":0.01562,"GHS":0.1788,"GIP":0.01562,"GMD":0.9243,"GNF":141.1552,"GTQ":0.133,"GYD":3.4174,"HKD":0.1353,"HNL":0.421,"HRK":0.1332,"HTG":1.9453,"HUF":7.1365,"IDR":259.0919,"ILS":0.05999,"IMP":0.01562,"INR":1.3949,"IQD":23.8415,"IRR":717.8181,"ISK":2.4479,"JEP":0.01562,"JMD":2.5882,"JOD":0.0122,"JPY":2.4632,"KES":2.0638,"KGS":1.3947,"KHR":67.2399,"KID":0.02624,"KMF":8.6956,"KRW":24.3376,"KWD":0.005154,"KYD":0.01433,"KZT":8.2208,"LAK":273.8169,"LBP":25.9315,"LKR":6.1903,"LRD":2.6162,"LSL":0.3071,"LYD":0.08099,"MAD":0.1845,"MDL":0.331,"MGA":68.8987,"MKD":1.0155,"MMK":35.7873,"MNT":53.4153,"MOP":0.1394,"MRU":0.6182,"MUR":0.7619,"MVR":0.2625,"MWK":17.5369,"MXN":0.3462,"MYR":0.07854,"MZN":1.0862,"NAD":0.3071,"NGN":7.3194,"NIO":0.6133,"NOK":0.1814,"NPR":2.2317,"NZD":0.02979,"OMR":0.006614,"PAB":0.0172,"PEN":0.06603,"PGK":0.05993,"PHP":1.0023,"PKR":4.0715,"PLN":0.08333,"PYG":118.1834,"QAR":0.06261,"RON":0.08681,"RSD":2.0444,"RWF":18.1732,"SAR":0.06451,"SBD":0.138,"SCR":0.2232,"SDG":9.3095,"SEK":0.1934,"SGD":0.02458,"SHP":0.01562,"SLE":0.2519,"SLL":251.8519,"SOS":9.2863,"SRD":0.4595,"SSP":10.8377,"STN":0.433,"SYP":42.7533,"SZL":0.3071,"THB":0.645,"TJS":0.1733,"TMT":0.05898,"TND":0.05427,"TOP":0.04078,"TRY":0.3166,"TTD":0.1157,"TVD":0.02624,"TWD":0.5443,"TZS":39.6052,"UAH":0.6335,"UGX":64.9736,"USD":0.0172,"UYU":0.6988,"UZS":187.3274,"VES":0.1434,"VND":407.0389,"VUV":2.0628,"WST":0.04733,"XAF":11.5942,"XCD":0.04644,"XDR":0.01352,"XOF":11.5942,"XPF":2.1092,"YER":4.2578,"ZAR":0.3072,"ZMW":0.2673,"ZWL":10.0256
I would like to format and make it look using javascript as data is getting fetched by javascript
function currencyexchange(currency1){
console.log(currency1);
$.ajax({
url: "php/currency.php",
type: 'POST',
dataType: 'json',
data: {
code:currency1
},
//if user enters correct data and api gives back the data then we run success funtion
success: function(result) {
console.log(JSON.stringify(result),null,4);
//if status of data is ok we fetch the data from fields and put them in results table in html
if (result.status.name == "ok") {
//fetching fields from api and showing them in html table
$('#exchangedata').html(JSON.stringify(result['data']).replace(/['"]+/g, '').slice(1,-1));
}else{
//if the upper condition fails
console.log("error");
}
},
//if there is no success in retrieving data from api
error: function(jqXHR, textStatus, errorThrown) {
console.log("error");
$('#txterror').html("Enter Valid Id");
}
});
Something like:
// add { and } to the json string (if it's not already there)
const data = `{ "RUB":1,"AED":0.06317,"AFN":1.5074,"ALL":2.0112,"AMD":7.0904,"ANG":0.03079,"AOA":6.9821,"ARS":2.4694,"AUD":0.02624,"AWG":0.03079,"AZN":0.02896,"BAM":0.03457,"BBD":0.0344,"BDT":1.7593,"BGN":0.03457,"BHD":0.006468,"BIF":33.7214,"BMD":0.0172,"BND":0.02457,"BOB":0.1177,"BRL":0.08918,"BSD":0.0172,"BTN":1.3948,"BWP":0.2247,"BYN":0.04456,"BZD":0.0344,"CAD":0.02333,"CDF":33.5622,"CHF":0.01691,"CLP":16.1531,"CNY":0.1225,"COP":74.4278,"CRC":10.7597,"CUP":0.4128,"CVE":1.949,"CZK":0.4341,"DJF":3.0571,"DKK":0.1319,"DOP":0.9116,"DZD":2.3957,"EGP":0.3326,"ERN":0.258,"ETB":0.8631,"EUR":0.01768,"FJD":0.03885,"FKP":0.01562,"FOK":0.1319,"GBP":0.01562,"GEL":0.04833,"GGP":0.01562,"GHS":0.1788,"GIP":0.01562,"GMD":0.9243,"GNF":141.1552,"GTQ":0.133,"GYD":3.4174,"HKD":0.1353,"HNL":0.421,"HRK":0.1332,"HTG":1.9453,"HUF":7.1365,"IDR":259.0919,"ILS":0.05999,"IMP":0.01562,"INR":1.3949,"IQD":23.8415,"IRR":717.8181,"ISK":2.4479,"JEP":0.01562,"JMD":2.5882,"JOD":0.0122,"JPY":2.4632,"KES":2.0638,"KGS":1.3947,"KHR":67.2399,"KID":0.02624,"KMF":8.6956,"KRW":24.3376,"KWD":0.005154,"KYD":0.01433,"KZT":8.2208,"LAK":273.8169,"LBP":25.9315,"LKR":6.1903,"LRD":2.6162,"LSL":0.3071,"LYD":0.08099,"MAD":0.1845,"MDL":0.331,"MGA":68.8987,"MKD":1.0155,"MMK":35.7873,"MNT":53.4153,"MOP":0.1394,"MRU":0.6182,"MUR":0.7619,"MVR":0.2625,"MWK":17.5369,"MXN":0.3462,"MYR":0.07854,"MZN":1.0862,"NAD":0.3071,"NGN":7.3194,"NIO":0.6133,"NOK":0.1814,"NPR":2.2317,"NZD":0.02979,"OMR":0.006614,"PAB":0.0172,"PEN":0.06603,"PGK":0.05993,"PHP":1.0023,"PKR":4.0715,"PLN":0.08333,"PYG":118.1834,"QAR":0.06261,"RON":0.08681,"RSD":2.0444,"RWF":18.1732,"SAR":0.06451,"SBD":0.138,"SCR":0.2232,"SDG":9.3095,"SEK":0.1934,"SGD":0.02458,"SHP":0.01562,"SLE":0.2519,"SLL":251.8519,"SOS":9.2863,"SRD":0.4595,"SSP":10.8377,"STN":0.433,"SYP":42.7533,"SZL":0.3071,"THB":0.645,"TJS":0.1733,"TMT":0.05898,"TND":0.05427,"TOP":0.04078,"TRY":0.3166,"TTD":0.1157,"TVD":0.02624,"TWD":0.5443,"TZS":39.6052,"UAH":0.6335,"UGX":64.9736,"USD":0.0172,"UYU":0.6988,"UZS":187.3274,"VES":0.1434,"VND":407.0389,"VUV":2.0628,"WST":0.04733,"XAF":11.5942,"XCD":0.04644,"XDR":0.01352,"XOF":11.5942,"XPF":2.1092,"YER":4.2578,"ZAR":0.3072,"ZMW":0.2673,"ZWL":10.0256}`;
// parse the JSON and for each entry of the parsed object create html
Object.entries(JSON.parse(data)).forEach( ([k, rate]) =>
document.body.insertAdjacentHTML(`beforeend`, `<div>${k}: ${rate}</div>`) );
Just Map over the Object Entries & put a <br/> after every key value pair. Or, using the same method, you can just create a new element for each item.
const result = {
data: {
RUB: 1,
AED: 0.06317,
AFN: 1.5074,
ALL: 2.0112,
AMD: 7.0904,
ANG: 0.03079,
AOA: 6.9821,
ARS: 2.4694,
AUD: 0.02624,
AWG: 0.03079,
AZN: 0.02896,
BAM: 0.03457,
BBD: 0.0344,
BDT: 1.7593,
BGN: 0.03457,
BHD: 0.006468,
BIF: 33.7214
}
};
document.body.innerHTML = Object.entries(result["data"])
.map(([k, v]) => `${k}: ${v}<br/>`)
.join("");
I got it formatted perfectly in different lines using the following code.
$('#exchangedata').html(JSON.stringify(result['data'],null, 4).replace(/['"]+/g, '').slice(1,-1).split(",").join("<br /><hr/>")
The .replace() regex helped to remove all the double quotes inside the json data
and .slice() helped with removing the curly braces from first and last index of data.
and split()and join () helped to remove the "," and place a line break after every currency

Incorrect operation of the jquery-ui autocomplete

Immediately after reloading the page when you enter a single character in the input, nothing happens. when you enter the following characters begins to complement.
Get data
`function getData(data, callback) {
$.ajax({
url: "myUrl" + encodeURIComponent(data),
method: "GET",
dataType: "JSON",
success: callback
})
}`
Callback function
`function autocompleteInput () {
var dataInput = $("#myInput").val();
function success(data) {
var dataArr = [];
for (var i = 0; i < data.data.length; i++) {
dataArr.push(data.data[i].name);
}
$("#myInput").autocomplete({
source: brokersNameArr,
delay: 500,
minLength: 1
})
getData(dataInput, success);
}`
Use in html
$("#myInput").keyup($.throttle(200, autocompleteInput));
Would suggest the following:
var dataArr = [];
$("#myInput").autocomplete({
source: function(req, resp){
$.getJSON("myurl?" + req.term, function(results){
$.each(results.data, function(k, r){
dataArr.push(r.name);
});
resp(results);
});
},
delay: 500,
minLength: 1
});
You might also want to review: http://jqueryui.com/autocomplete/#multiple-remote
Using a Function for source will give you the ability to manage how the data is sent and received.
Function: The third variation, a callback, provides the most flexibility and can be used to connect any data source to Autocomplete, including JSONP. The callback gets two arguments:
A request object, with a single term property, which refers to the value currently in the text input. For example, if the user enters "new yo" in a city field, the Autocomplete term will equal "new yo".
A response callback, which expects a single argument: the data to suggest to the user. This data should be filtered based on the provided term, and can be in any of the formats described above for simple local data. It's important when providing a custom source callback to handle errors during the request. You must always call the response callback even if you encounter an error. This ensures that the widget always has the correct state.
Hope this helps.

Ajax can success() handle two type of return?

Working in a C# ASP.NET project with JavaScript/Jquery/jqGrid.
New task is to have a page to i) accept an Excel input file, ii) use the column ID to look up additional information, and iii) generate a new Excel file using some columns from input file and all columns returned from database.
I have completed that, but just want to do a bit more error handling. In the stored procedure, if everything works fine, it returns a data table (or in Oracle term, a CURSOR). If there is an error, I have added a catch block and return an error message.
I modify the AJAX call. Beside adding dataType as 'text', I expect the return as XML.
$.ajax({
// POST
// URL: url to call that stored procedure
dataType: text,
success: function (response) {
// now the response is XML (don't know why...
// specify dataType as 'text', but get XML...)
// If response contains 'string' tag, report error.
},
failure: ...
})
Here is what I used to do. I don't specify the dataType but somehow that works.
$.ajax({
// POST
// ... rest is same but without the dataType
success: function (response) {
Download( response )
// The file is already and placed in Download directory.
// Call 'Download()' will actually make the download happen
// But here response is just a path to the Download directory +
// download file name.
And Download() is:
function Download(url) {
document.getElementById('my_iframe').src = <%=ResolveUrl("~/")%> +url;
return false
};
How can I have the success function handle both type of response?
(Just for your information: The front-end page is ASP.NET. Button click will call a JavaScript function. The function calls a web service function via $.ajax(). As there are many rows, the web service function calls a function in a database class many times - each time pass in just one ID. The function will in return call stored procedure.)
Edit: Thanks for solution from Mustapha Larhrouch. Here are some points that I have to adjust:
Add dataType.
If response is XML, check if error.
If not XML, just download.
And here is my code:
$.ajax({
// POST
// URL
dataType: "text",
success: function (response) {
if (isXML(response)) {
var xmlDoc = $.parseXML(response);
$xml = $(xmlDoc);
var errMsg = $xml.find("string").text();
if (errMsg != "" ) {
// pop up a dialog box showing errMsg
}
}
else {
Download(response);
}
you can check if the response is an xml if it's parse it, if not the response is a string. and you can use this function to check if the response is an xml :
function isXML(xml){
try {
xmlDoc = $.parseXML(xml); //is valid XML
return true;
} catch (err) {
// was not XML
return false;
}
}
$.ajax({
// POST
// ... rest is same but without the dataType
success: function (response) {
if(isXML(response){
Download( response )
}
else{
//report as error
}

jquery Autocomplete - not filtering

I am trying to user JQuery autocomplete function with an ajax call in it, which will return the list of Strings..when i am trying to type, it is showing all the list of strings and not filtering out based on the input..Not sure where i am going wrong..Below is my autocomplete function..
$("#domainNameId").autocomplete({
source : function(request, response) {
console.log("in ajax ");
$.ajax({
url : "getAllDomains",
type : "GET",
contentType : "application/json",
data : {
env : $("#environment").val()
},
dataType : "json",
success : function(data) {
response(data); // list of strings..
},
error : function(x, t, m) {
console.trace();
if (!(console == 'undefined')) {
console.log("ERROR: " + x + t + m);
}
console.log(" At the end");
}
});
},
});
appreciate the help..
Your backend seems to always return the entire data and not do any filtering ( The service name itself is getAllDomains). In that case there is no need to use the function form of source option to make ajax calls.
What you're doing is sending multiple AJAX requests to the server as the user types. If your backend always returns the same data, there is no point in sending multiple requests to it. You can simply fetch the data once and then initialize the autocomplete with the response as source, then the widget will do the filtering as user types.
The docs says:
A response callback, which expects a single argument: the data to suggest to the user. This data should be filtered based on the provided term.
So if your server doesn't do the filtering, don't use the function form to make AJAX requests.
do something like:
$(function() {
// make a one-time request
$.ajax({
url: "getAllDomains",
type: "GET",
contentType: "application/json",
dataType: "json",
success: function(data) {
// init the widget with response data and let it do the filtering
$("#domainNameId").autocomplete({
source: data
});
},
error: function(x, t, m) {
console.trace();
if (!(console == 'undefined')) {
console.log("ERROR: " + x + t + m);
}
console.log(" At the end");
}
});
});
In the success callback, you will need to filter the data yourself using the request.term passed to the source function.
There is more information on the jQuery Autocomplete source here: https://api.jqueryui.com/autocomplete/#option-source.

JavaScript: search user input in number of arrays

I am working with D3js library. On the web page, there is a search box which user can input their parameter. I receive arrays of data via Ajax post to my database. Following is the code:
..........
var aa;
var bb;
$(function(){
$.ajax({
type: "POST",
url: "http://localhost:7474/db/data/transaction/commit",
accepts: {json: "application/json"},
dataType: "json",
contentType: "application/json",
data: JSON.stringify(query), //query is somewhere above the code
//pass a callback to success to do something with the data
success: function (data) {
aa = data.results[0].data;
aa.forEach(function (entry) {
passVar(entry.row[0].name)
});}}
);
});
function passVar(smth){
bb =[smth];
console.log (bb);
//Should search the user input..........
}
//if the user input matches, filter function should run.........
function filterData() {
var value = d3.select("#constraint")[0][0].value;
inputValue = value;
............
}
As the result of console.log(bb)I receive the following on console:
["Direct Digital Control System"]
["Fire Protection"]
["HVAC Cooling- Waterside"]
["HVAC Heating- Waterside"]
["HVAC System"]
["HVAC-01"]
["HVAC-02"]
What I want to do:
If the user input match with one of the results in var bb, then program should run function filterdata() {....for querying. If not, don't do anything.
How should I write the code to make the search and run the other function? Thanks for the any help/suggestion.
You can loop through the array and find whether the user input is equals to the current index value of the array. if equals you can call your function and break the loop since no need to loop further more.
for(int i=0; i<bb.length; i++){
if(bb[i] == userInput){
filterdata();
break;
}
}

Categories

Resources