Asynchronous Lazy Loading - javascript

currently, we are using the SAP HANA Database. To get data, we will use a Node.JS-API, which we will call via AJAX, to get the advantages by async. So here is the problem:
We have many pages where we need the same data (e.g. customer data). To do so, I wanted to create a Library, which does the actual data calls, so that i just need to call db.getCustomer([ID]). In order to get a return value from AJAX, I have to set async: false within the AJAX call.
My question is now, is it possible to create a data-call-library asynchronously? Is it a good practice to encapsulate the databinding (using so called DAO)?
I'm a bit confused, because another dev told me to just use the same AJAX-call over and over again, to not loose the async and it is a better practice anyway.
Here is my actual AJAX-call as an example:
getCustomer: function( CID ) {
var aUrl = 'http://example.com/api/customer/' + CID,
returnData
;
jQuery.ajax({
url: aUrl,
method: 'GET',
dataType: 'json',
contentType: "application/json",
async: false,
success: function(data) {
returnData = data;
}
});
return returnData;
},
// other ajax calls
// to get the data via 1-liner
thank you for clarification!

Actually, it makes no sense to return data from a callback in a synchronous function; normally, you would store the returned callback data into your model, so your view/controller gets automatically updated.
If you really need your method to return async data, have a look at Deferred or Promises

Related

How to access ajax jsonp results data in order to return true or false?

I have a function that needs to either return true; or return false; which contains an ajax call that is the method for determining the conditional result based on the response.
My problem is scoping and I'm not sure how to get out of this one. If I setup as a callback, then the return statement lives within the callback function itself and doesn't execute within the main wrapper function.
How should this be setup to execute correctly? Do I need to completely restructure?
function() {
var response;
$.ajax({
dataType: 'jsonp',
url: 'https://apilayer.net/api/check?access_key=',
async: false,
success: function(json) {
response = json.score;
}
});
if (response == 1) {
return false;
}
};
dataType: 'jsonp',
async: false,
JSONP requests cannot be made syncronously, so async: false is ignored.
If you weren't making a JSONP request, then using async: false would still be a bad idea (the underlying feature it depends on is deprecated for good reason).
This means that you can't do what you want.
The answers to How do I return the response from an asynchronous call? describe strategies for dealing with this.
First of all, 'async = false' is not supported anymore so call will be async in nature.
Now, you have two options:
initialize conditional var i.e. response with some value. So even if
ajax response is not received, you will not face any error on if
condition.
put conditional statement inside callback.
If your condition is based on ajax response, then ideal way would be to put it inside callback function.
Hope it helps!
if you use async false the request will become synchronous and the code will not be executed until the request is completed. this will slow down the browser.
var response = $.ajax({
dataType: 'jsonp',
url: 'https://apilayer.net/api/check?access_key=',
async: false,
success: function(json) {
response = json.score;
}
});

How to run getJSON synchronously? [duplicate]

GOAL: What I'm after is to get data from database and refresh main.php (more evident through draw_polygon) every time something is added in database (after $.ajax to submit_to_db.php).
So basically I have a main.php that will ajax call another php to receive an array that will be saved to database, and a json call another php to return an array will be used by main.php.
$(document).ready(function() {
get_from_db();
$('#button_cancel').click(function(){
$.ajax({
url: 'submit_to_db.php',
type: 'POST',
data: {list_item: selected_from_list},
success: function(result){
...
get_from_db();
}
});
});
function get_from_db(){
$.getJSON('get_from_db.php', function(data) {
...
draw_polygon(data);
});
}
});
In my case, what I did was a get_from_db function call for getJSON to actually get data from database, with the data to be used to draw_polygon. But is that how it should be done? I'm a complete newbie and this is my first time to try getJSON and ajax too to be honest. So my question: How does asynchronous work actually? Is there another workaround for this instead of having to call function get_from_db with getJSON (it isn't synchronous, is it? is that why it doesn't update the page when it isn't within a function?) All the time - like $.ajax with async: false (I couldn't get it to work by the way). My approach is working, but I thought maybe there are other better ways to do it. I'd love to learn how.
To make it more clearer, here's what I want to achieve:
#start of page, get data from database (currently through getJSON)
Paint or draw in canvas using the data
When I click the done button it will update the database
I want to AUTOMATICALLY get the data again to repaint the changes in canvas.
Since $.getJSON() uses ajax configurations, just set the global ajax configs:
// Set the global configs to synchronous
$.ajaxSetup({
async: false
});
// Your $.getJSON() request is now synchronous...
// Set the global configs back to asynchronous
$.ajaxSetup({
async: true
});
Asynchronusly does mean the Request is running in the background, and calls your function back when it got a response. This method is best if you want to have a result but allow to use your app within the request. If you want to have a direct response, take a look at a synchron request. this request will pause script execution until it got a response, and the user can not do anything until the response was recieved. You can toggle it via:
async: false,
So for example:
$.ajax({
url: "myurl",
async: false,
...
})
$.getJSON(), doesn't accept a configuration, as it says in the docs it's a shorthand version of:
$.ajax({
dataType: "json",
url: url,
data: data,
success: success
});
So just rewrite your request in terms of that and async:false will work just as you expect.
$.getJSON() is a shorthand notation for $.ajax() which can be configured to be synchronous (see jQuery.getJSON and JQuery.ajax):
$.ajax({
dataType: "json",
url: url,
data: data,
async: false,
success: function(data) {
...
draw_polygon(data);
}
});
Try to avoid synchronous calls though. Quote from jQuery doc (see async prop):
Cross-domain requests and dataType: "jsonp" requests do not support
synchronous operation. Note that synchronous requests may temporarily
lock the browser, disabling any actions while the request is active.
You might want to try jQuery Deferreds like this:
var jqxhr = $.getJSON(url);
jqxhr.done(function(data) {
...
draw_polygon(data);
});

Use data from ajax call without using async: false

I'm pretty new to JS/ajax and was a bit confused on ajax data/success returns.
I have the following ajax code. I want it to run the code in succes: after the ajax call has received the json from the imgur api.
It is only working for me with async: false. I thought the bit in success: would only run after the data has been retrieved, but for some reason data is null if aysnc is true.
I've read a lot of SO answers/jQuery documentation but I can't seem to figure out how to get it to not hang the browser with async: false
This code might be running 100+ times on a page (i.e. reddit.com/r/pics with 100 links loaded on one page), so async: false is not only bad practice but also renders the page unusable for 5 to 6 seconds, which is unacceptable.
I've tried making ajax a var then calling that var .success(function(data) ...); but it still does not work. I've also tried replacing success with complete.
It all only ever works with async: false
Any suggestions would be greatly appreciated!
Thanks!
$.ajax({
type: "GET",
url: "https://api.imgur.com/3/gallery/" + hash,
dataType: "json",
headers:{
'Authorization':'Client-ID c606aeeec9ca098'
},
async: false,
success: function(data) {
if(data.data.is_album == true) {
if(data.data.images_count == 1){
el[j].href = el[j].href.replace(/(http(s)?:\/\/)?(www\.)?(m\.)?imgur.com\/gallery\/.*/, data.data.images[0].link);
}else{
el[j].href = el[j].href.replace(/(http(s)?:\/\/)?(www\.)?(m\.)?imgur.com\/gallery\//, "https://imgur.com/a/");
}
}
else{
el[j].href = el[j].href.replace(/(.*)?(http(s)?:\/\/)?(www\.)?(m\.)?imgur.com\/.*/, data.data.link);
}
}
});
You might find the jQuery Deferred object (Promises interface) to be helpful. It allows you to do stuff like:
var promise = $.ajax("/myServerScript1");
function getStuff() {
return $.ajax("/myServerScript2");
}
promise.then(getStuff).then(function(myServerScript2Data){
// Do something with myServerScript2Data
});
Resource (this is well written and a necessary read for anyone using AJAX):
http://www.htmlgoodies.com/beyond/javascript/making-promises-with-jquery-deferred.html
I can't see what doesn't work on your code but I can tell you what is not recommended.
Always have a failure handler : You have to put a function in the fail field of your request object. If you don't, you will not be able to see any errors.
Keep the test simple : You should begin by only displaying the value of the request result instead making some calculation with it. This way you can debug ONLY the request call and you are sure that the problem doesn't came from the calculation code
Use Promises API : As previously pointed by the #gibberish, the modern way to do what you want is to use Promises. You can use jQuery's promises or any other like ES6 Promises (that one requires a compilation time for most of browsers)

Adding a settings file to a front-end web application in an async manner

I'm currently trying to resolve some with an SPA being built with a lot of custom components, borrowing a lot from all over the place.
The current challenge I have is initializing some settings (Endpoint URLs and the sort) with a settings file to be set on a per-deployment basis. It's Javascript, so it makes sense to relegate this to a JSON file. However, a lot of the logic is still written in this strongly-defined OO methodology, and I am trying to determine the best method to load this settings file within the async methodology.
Looking at other topics on Stack Overflow, the jQuery getJSON method is a viable option. But I am not clear if it is still based on synchronous calls. Furthermore, If there is an async option, I want to be sure that the value is loaded before firing any additional logic in the application (instead of having it initialize nothing at the constructor).
Is my assumption correct? Is getJSON the best approach here? Code is listed below.
var settings = $.getJSON("conf.json");
var SearchObject = new Search(settings);
// Remainder is just a bunch of bind() and on() calls
$.getJSON is just a shortcut for more detailed $.ajax call where you can adjust much more parameters, like callback if you need. And no, $.getJSON same as $.ajax
Perform an asynchronous HTTP (Ajax) request.
http://api.jquery.com/jQuery.ajax/
The getJSON jquery function is async by default.
$.getJSON({
url: url,
data: data,
success: function(data, textStatus, jqXHR ){}
});
It is the same as:
$.ajax({
dataType: "json",
url: url,
data: data,
success: function(data, textStatus, jqXHR ){}
});
But, with the ajax function you can set async to false if you want.
eg.
$.ajax({
dataType: "json",
async: false,
url: url,
data: data,
success: function(data, textStatus, jqXHR ){}
});

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