Create wrapper function around ajax calls - ajax

I want to create a wrapper around my API calls in AngularJS like
function MakeCall (url){
$http.get(url, config).success(successfunction);
return response;
}
Can you help me how to wait for the call to complete and get the final response from the call. In above code the "return response" is what I want to get after the completion of call. This function will be used like
response = MakeCall("to some url");

response = MakeCall("to some url");
That's not how promises work. You cannot synchronously return the result of an ajax call.
You just seem to want to return the promise that $http.get() already yields from your function:
function MakeCall (url){
return $http.get(url, config).success(successfunction);
}
Then use it like this:
MakeCall("to some url").then(function(response) {
…
});

Related

JS: Async function with await statement results in undefined promise. What am I doing wrong? Simple example

I'm new to JS and am currently immersing myself in asynchronous functions and promises. Having quite some experience in Python and R, this is totally new for me. I read many different websites, topics and solutions for returning a value in an asynchronous function - but I can't get it to work. Below I boiled it down to a simplification of the function I wrote, designed to get information from google about a location and return it. Simple as that. I followed the advice online and tried to rewrite the following advice from Benjamin Gruenbaum on How do I return the response from an asynchronous call?.
async function foo(){
var data = await fetch("/echo/json"); // notice the await
// code here only executes _after_ the request is done
return data.json(); // data is defined
}
Please see my own code below. It seems to me that it I'm doing the same thing, but it still logs as Promise {<pending>}... What am I doing wrong? data should be an array. Even if I only replace my googleapi url and use fetch() and .json(), it logs as Promise {<pending>}.
async function foo() {
var data = await axios.get("https://maps.googleapis.com/maps/api/geocode/json?address=Amsterdam&key=API_KEY");
return data;
}
console.log(foo())
try This way of calling async function
async function foo()
{
let response = await fetch(`https://maps.googleapis.com/maps/api/geocode/json?address=Amsterdam&key=API_KEY`);
let data = await response.json()
return data;
}
foo().then(data => console.log(data));
Can you try below code to know what is going on in the "data" you got .
This is not the solution of your problem but just you will know what you got in result
console.log(JSON.stringify(foo()));

How to avoid loop in Ajax call

I have function getData() which make an ajax call and retrive JSON data. On success i call another function which is marquee() . inside marquee on finish event i call getData() again, But each time getData() when get called, it increases it's request to mentioned file data.php, For example on first call it call once, Second call it request twice, and then twice become 4times,8times and more and more, how to avoid this?!
function getData()
{
$.get('data.php).done(function(response)
{
var data = JSON.parse(response);
if(data.Direction == "left")
{
$(".marquee").html("<span data-direction='"+data.Direction+"'>"+data.Message+"</span>");
}else if(data.Direction == "right"){
$(".marquee").html("<span data- direction='"+data.Direction+"'>"+data.Message+"</span>");
}
});
}
function marquee()
{
$(".marquee").marquee({duration : 10000}).bind("finished",function()
{
getData();
});
}
I hope i was clear... Appreciate each answer.
Every time you are calling marquee function, you are basically binding an event finished on to it. On multiple such function calls, you will have duplicate events. In your code setup, you need to unbind the function before binding it. Something like
$(".marquee").marquee({duration : 10000}).unbind("finished",getData).bind("finished",getData)
Ideally, you should bind only once so you do not have to unbind it again and again.

How to repeat ajax call until a specific value is returned by the server?

I need to populate a progressbar, I have a service giving me the current progress.
My idea would be something like:
$http.get('service').success(function(response, status, headers, config){
$scope.progress = response.progress;
$scope.progressL = response.progress+"%";
if(response.progress < 100){
//repeat
}
Just place the api call in a function, and let the handler call it:
function checkProgress(){
$http.get('service').success(function(response, status, headers, config){
$scope.progress = response.progress+"%";
if(response.progress < 100){
checkProgress();
}
}
}
Though, you'll probably want to cap it in some way. You might also want to add a timeout so that it waits a while between checks, something along the lines of $timeout(checkProgress, 5000).
EDIT for clarity: The reason this won't overflow your stack is that Angular's promises $q, which the Promise returned by $http.get('service') is implemented by, will trigger asynchronously.
So In the following case:
$http.get('service').success(function(){ console.log('callback'); });
console.log('Returning');
return;
The console will say "Returning" before "callback" every time.
When the resolution is guaranteed to be async, you're fine. Here's a demo of resolving async thousands of times: http://jsfiddle.net/23Ldaj42/
Were this not the case (as in, if $http callbacks were not guaranteed to be called async), instead you'd want to protect yourself by forcing it to be async as follows:
function checkProgress(){
$http.get('service').success(function(response, status, headers, config){
$scope.progress = response.progress+"%";
if(response.progress < 100){
$timeout(checkProgress); // This will perform async
}
}
}
You could call this recursively:
var callback = function(response, status, headers, config){
$scope.progress = response.progress;
$scope.progressL = response.progress+"%";
if(response.progress < 100){
$http.get('service').success(callback);
}
};
$http.get('service').success(callback);

AJAX + jQuery Deferred: execution sequence

Task: get data from server with $.post, process them by method .success(), after that call some function.
var t;
$.when($.post("get_json.php", function(res) {
t = res;
}, 'json')).done(function() {
console.log(t);
});
Do I understand correctly that the Deferred method .done() is executed after .success is done (ie t = res)?
But why "console.log(t)" shows "undefined"?
Is .done() fires after request, but before .success()?
Passing a "success" callback to $.post() is an alternative to the (preferred) chaining of .done(...). Do one or the other, not both, then you don't need to worry about the execution order.
Also, unless you have a decent caching strategy for async data, you shouldn't be setting t as an outer var.
$.post("get_json.php", ...).done(function(t) {
console.log(t);
//do awesome things with t here
});
Caching would be something like this :
var asyncCache = {};
...
function get_t() {
return (asyncCache.t) ? $.when(asyncCache.t) : $.post("get_json.php", ...).done(function(t) {
asyncCache.t = t;
});
}
...
get_t().done(function(t) {
console.log(t);
//do awesome things with t here
}
$.when() is ONLY needed when you have multiple promises and you want to wait for all of them to complete. You simply don't need it at all for your single ajax call. You can just do it like this:
$.post("get_json.php").done(function(t) {
// use the results of the ajax call here
console.log(t);
});
In addition, your code example was using BOTH a success callback function AND a .done() handler. Pick one of the other, not both as they are different ways of getting a callback when the ajax call is done. I'd suggest the promise implementation above because it's more flexible. But, you could also use just the success handler:
$.post("get_json.php", function(t) {
// use the results of the ajax call here
console.log(t);
}, 'json');
Note, when you have an asynchronous operation like this, you need to consume the results of the ajax call in the success callback (or the promise callback) or call some function from there and pass it the data. You do not want to put the data into a global variable or a variable in a higher scope because other code will simply have no way of knowing when the data is ready and when it is not. Put your action in the callback.
If you have more than one ajax call that you want to wait for, then you can do it like this:
$.when($.post("get_json.php"), $.post("get_json2.php")).done(function(r1, r2) {
// use the results of the ajax call here
console.log(r1[0]); // results from first ajax call
console.log(r2[0]); // results from second ajax call
});

Jasmine use it to over ride and test a method that uses aiax

I have a JS file that contains many methods, ajax caller is constant.
function ajaxCaller(data,url,callback) { //standard jquery ajax call here }
function method1(){
// ... does work ... then
ajaxCaller(data,url,function(){ // changes the dom } );
}
How can I use jasmine to over ride the ajaxCaller method that is being called by nearly every method in my js file such that I can test that the DOM is getting changed?
Probably you have something like the code below, right?
function ajaxCaller(data, url, callback) {
$.ajax(url, { data: data, success: callback });
}
In this case you can mock the jQuery ajax method so that instead of real AJAX request the function you provide will be called. It is possible to define the response you want to be "returned from the server". Jasmine andCallFake function will do it for you:
it ('when some response returned from the server, something happens', function() {
var response = {}; // ... define the response you need
spyOn($, 'ajax').andCallFake(function(url, options) {
options.success(response);
});
method1();
// and assert that something really happens ...
});

Resources