how to wait check ajax request has completed before other element? - javascript

I have following code, where for each Image it makes ajax call. but my problem is like when it make ajax call for first image,at that time without waiting for respose it invokes for the second.so it hasn't get effect of first call,means I missed the first call effect. similary without waiting for second it is inovking for third,...
so how to wait in above each function until response come?
jQuery('.xxx img[src*="mainimage"]').each(function () {
vobj = $(this);
var inmainurl = 'https://xxx.kki/api/oembed.json?url=' + $(this).attr('src');
$.ajax({
url: inmainurl,
dataType: 'json',
success: function (result) {
$(vobj).attr('src',result.thumbnail_url);
}
});
});

You should use a recursive function for these purposes. Basic example (jsFiddle):
var myMethod = function(index){
var total_images = $('img').length;
if( index == total_images ) return; // job finished
var current_image = index || 0;
$.ajax({
/*...*/
success: function(/*...*/){
/*...*/
myMethod(current_image + 1);
}
});
};
myMethod();

You could make it synchronous by adding async: false to the ajax parameters. Then you can call them one after the other.
Or, if you want a bit more flexibility, put the ajax call into a function, passing in the image to load. Then in the "success" method of the ajax call, call the function again, passing in the next image name. You'll need some sort of list of image names so that the recursive calls can work out the next image to pass in, in each case.

After every ajax success callback, set some data-* attribute to loaded element and call the same function again.
Try this:
function loadOnlyOneImage() {
var vobj = $('.xxx img[src*="mainimage"][data-loaded!="true"]:first');
if (vobj.length) {
var inmainurl = 'https://xxx.kki/api/oembed.json?url=' + vobj.attr('src');
$.ajax({
url: inmainurl,
dataType: 'json',
success: function(result) {
vobj.attr('src', result.thumbnail_url);
vobj.attr('data-loaded', true);
loadOnlyOneImage();
}
});
}
}
loadOnlyOneImage();

Related

Ajax saving array into global variables not working keep getting undefined

Trying to save an array retrieved from ajax into a global variable such that I may use it later on but keep getting undefined error
<script>
var items = [];
function add(value){
items.push(value);
}
$(document).ready( function() {
$.ajax({
type: 'POST',
url: 'xxxx.php',
dataType: 'json',
cache: false,
success: function(result) {
for(i=0; i < result.length; i++){
add(result[i]);
}
},
});
});
document.write(items[1])
</script>
This is an asynchronous AJAX call. The call to add will be done at a later time than the execution of document.write(items[1]);
So this is the right way to do it:
<script>
var items = [];
function add(value){
items.push(value);
}
$(document).ready( function() {
$.ajax({
type: 'POST',
url: 'xxxx.php',
dataType: 'json',
cache: false,
success: function(result) {
for(i=0; i < result.length; i++){
add(result[i]);
}
document.write(items[1])
},
});
});
</script>
This way the function that uses the result, will be executed when the result function is executed.
Think it this way: you said: Here is this lemon basket. Then you asked someone to go somewhere and get the lemons and before he returned you tried to count the lemons. Got it ?
You can use ajaxstop to call the method after the ajax request has completed. Place the following function in document ready:
$(document).ajaxStop(function () {
document.write(items[1]);
});
The above solution works but this is another option I used when waiting for multiple ajax functions to complete. This will call every time you complete an ajax request but there is a way to limit to one call if need be.

multiple ajax async not in order and need synchronous behavior

Sorry, My first language is not English. I am not sure that if I explain my question properly.
My code is like a main function have two ajax functions (Use ajax function to get foursquare API)
main(){
ajax1();
ajax2();
all other codes
}
the ajax2() function has to get result from ajax1() as input and then return result(actually result was pushed in to global array).
all other codes should be processed after two ajax functions are finished. I tried the asyn: false but it is not working. My html file include newest jquery like this
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js" ></script>
I try the jquery function $.when().done() function and the first ajax works. However, the second ajax() function was in the for loop. The for loop will destroy the mechanism of $.when().done() function:
first ajax: in firstjson function
Second ajax: in transfer function
function firstjson(tmpName,tmpLoc,PhotoJson,foursq){
return $.ajax({
type: 'GET',
url: foursq,
dataType: 'jsonp',
success: function(json) {
for (i = 0; i < 3; i++) {
var resultname = json['response']['venues'][i].name;
var resultlocation = json['response']['venues'][i].location;
var resultlat = resultlocation.lat;
var resultlng = resultlocation.lng;
var tmpmarker = new google.maps.LatLng(resultlat,resultlng)
tmpName.push(resultname);
tmpLoc.push(tmpmarker);
var resultid = json['response']['venues'][i].id;
var tmpPhotoJason = 'https://api.foursquare.com/v2/venues/'+ resultid +'/photos?';
PhotoJson.push(tmpPhotoJason);
}
}
});
}
function transfer(PhotoJson,PhotoURL){
for (i = 0; i < 3; i++) {
return $.ajax({
type: 'GET',
url: PhotoJson[i],
dataType: 'jsonp',
success: function(json) {
resultphoto = json['response']['photos']['items'];
photoprefix = resultphoto[i].prefix;
photopresuffix = resultphoto[i].suffix;
photourl = photoprefix+"150x150" + photopresuffix;
PhotoURL.push(photourl);
}
});
}
}
$.when(firstjson(tmpName,tmpLoc,PhotoJson,foursq)).done(function(){
alert("test1");
$.when(transfer(PhotoJson,PhotoURL).done(function(){
console.log(PhotoURL);
all other codes!!!!
});
});
//PhotoURL is global array
So the first "when" function work properly. alert("test1") work after the firstjson was done. However the for loop inside transfer function will break the when function. How can I fix the problem. Please help me. I will appreciate you can give me any related information. Thanks!!!
This will execute ajax2 after ajax1
function anotherMethod(){
//Here you do all that you want to do after the last $ajax call
}
main(){
firstjson(tmpName,tmpLoc,PhotoJson,foursq)
.then(transfer(PhotoJson,PhotoURL))
.then(anotherMethod);
}
As you are returning a promise from the first with the "return $ajax..."
So you organice your code like this:
in methods with ajax calls you return the call as you are doing now
return $.ajax();
that returns a promise that you chain.
And you put what you want to do in another method so you call it in the last "then".
Non-Blocking Example
You should use non-blocking code. You can turn async off (async: false) but this can easily be done in a non-blocking manor using callback functions.
function main(){
$.ajax({ // First ajax call (ajax1)
url: "first/ajax/url",
type: "GET", // POST or GET
data: {}, // POST or GET data being passed to first URL
success: function(x){ // Callback when request is successfully returned
// x is your returned data
$.ajax({ // Second ajax call (ajax2)
url: "second/ajax/url",
type: "GET", // POST or GET
data: {
thatThing: x
}, // POST or GET data passed to second URL
success: function(y){
// y is your second returned data
// all other codes that use y should be here
}
});
}
})
}
This would be the non-blocking approach, nest your function within "success" callback functions. Nest ajax2 within ajax1's "success" callback to ensure that ajax2 is not executed before ajax1 has returned and nest your "all other codes" inside the "success" callback of ajax2 to ensure they are not executed until ajax2 has returned.
Blocking Example
If you absolutely must (please avoid at all cost) you can disable async which will block all JavaScript code from executing until the ajax has returned. This may cause your browser to temporarily freeze until the ajax request has returned (depending on the browser).
function main(){
var x = ajax1();
var y = ajax2(x);
window["y"] = y; // push to global as you requested but why?
// All other codes that can now use y
}
function ajax1(){
var x;
$.ajax({
url: "first/ajax/url",
async: false,
type: "GET", // POST or GET,
data: {}, // POST or GET data being passed to first URL
success: function(r){x=r}
});
return x;
}
function ajax2(x){
var y;
$.ajax({
url: "second/ajax/url",
async: false,
type: "GET", // POST or GET,
data: {
thatThing: x
}, // POST or GET data being passed to second URL
success: function(r){y=r}
});
return y;
}
Once again I stress, try not to disable async that will cause your code to block and is BAD code. If you absolutely 100% have to for some reason than than it can be done but you should attempt to learn how to write non-blocking code using callbacks as the first example does.
Social Network Example
Now I'll do an example of an ajax call to get an array of your friends IDs, and then a series of ajax calls to get each of your friends profiles. The first ajax will get the list, the second will get their profiles and store then, and then when all profiles have been retrieved some other code can be ran.
For this example, the url https://api.site.com/{userID}/friends/ retrieves an Object with a list of friends IDs for a particular user, and https://api.site.com/{userID}/profile/ gets any users profile.
Obviously this is a simplified api as you will probably need to first establish a connection with a apikey and get a token for this connection and the token would likely need to be passed to the api uris but I think it should still illustrate the point.
function getFriends(userID, callback){
$.ajax({
url: "https://api.site.com/"+userID+"/friends/",
success: function(x){
var counter = 0;
var profiles = [];
for(var i=0;i<x.friendIDs.length;i++){
$.ajax({
url: "https://api.site.com/"+x.friendIDs[i]+"/profile/",
success: function(profile){
profiles.push(profile);
counter++;
if(counter == x.friendIDs.length) callback(profiles);
}
});
}
}
});
}
getFreinds("dustinpoissant", function(friends){
// Do stuff with the 'friends' array here
})
This example is "Non-blocking", if this example were done in a "blocking" way then we would ask for 1 friends profile, then wait for its response, then request the next and wait and so on. If we had hundreds of friends you can see how this would take a very long time for all ajax calls to complete. In this example, which is non-blocking, all requests for profiles are made at the same time (within 1ms) and then can all be returned at almost exactly the same time and a counter is used to see if we have gotten responses from all the requests. This is way way way faster than using the blocking method especially if you have lots of friends.

how to use properties and methods withing a JavaScript class to exchange data?

i have small issue with exchanging data in between methods in a JavaScript object (class):
var TEST = (function () {
var TEST = function() {
};
TEST.prototype.get = function() {
$.ajax({
type: "GET",
url: "http://test.com/getall",
dataType: "json",
success: function (data) {
return data; // if i console log this i will get a json obj
}
});
};
TEST.prototype.parse = function(data) {
$.each(this.get(), function(k, v){
console.log(v);
});
};
return TEST;
})();
so i am trying to call one method in the each statement in another method. the issue is that
the response is undefined.
i also tried it like this, but with he same result
var testing = new TEST();
var get = testing.get();
testing.parse(get);
What am i missing? how can i return the data from this.get to be used in this.parse.
thanks
$.ajax() per default is asynchronous. That means, that the execution of your function get() wont wait until the request is finished. Hence you return no value from it, which results in undefined being returned.
In order to have your get() function be able to return a value, you would have to do the request in a synchronous way and set a variable in the outer function (as success itself is just another function, whose return value is not caught):
TEST.prototype.get = function() {
var result;
$.ajax({
type: "GET",
url: "http://test.com/getall",
async: false, // this is the important part!
dataType: "json",
success: function (data) {
result = data;
}
});
return result;
};
EDIT
As mentioned by #pebbl, this will halt the execution of all your scripts, until the request is done. Hence your whole page will be blocked for the time being.
The general approach is to use callbacks in such cases, which will be executed once the requests finished. So in your case something like this:
TEST.prototype.get = function( cb ) {
$.ajax({
type: "GET",
url: "http://test.com/getall",
dataType: "json",
success: function (data) {
cb( data );
}
});
};
with later on calling like this:
var testing = new TEST();
testing.get( function( data ) {
testing.parse( data );
});
You can't construct your function this way as you are relying on an asyncronous call, which will return it's result outside of the normal execution flow. The only way you can actually receive the result of your .get function is to use a callback.
Put simply your value isn't being returned from the .get function, it's being returned from the callback you are passing into jQuery's .ajax method.
You'd be far better off redesigning your code so as to still support the asyncronous call -- rather than disabling async.
A rough idea is to change your parse function like so:
TEST.prototype.parse = function(data) {
this.get(function(result){
$.each(result, function(k, v){
console.log(v);
});
});
};
And to change your get function accordingly:
TEST.prototype.get = function(callback) {
$.ajax({
type: "GET",
url: "http://test.com/getall",
dataType: "json",
success: callback
});
};
The above is just a quick example, you'd be wise reading up on the following jQuery topics:
http://api.jquery.com/promise/
http://api.jquery.com/category/deferred-object/
If you design your code around the promise pattern you'll find it complicated at first, but it gives you a lot of power in your code -- and gets around the whole callback stacking madness you can end up with when dealing in ajax calls.
Whilst it's not entirely clear from the jQuery.ajax documentation, this function returns a jqXHR object which implements the promise interface. So this means you can use the promise methods done, always and fail.
http://api.jquery.com/jQuery.ajax/

Looping through array with callback

I am trying to run through a array send to a php file and on a callback send the next value after the php has completed its download. Here what i have so far.
my array come through as follows.
["http://example.com/test1.zip", "http://example.com/test2.zip", "http://example.com/test3.zip", "http://example.com/test4.zip", "http://example.com/test5.zip"]
above is the output from console.log(values); below. it grabs some urls from checkbox values.
$('.geturls').live('click',function(){
var values = new Array();
$.each($("input[name='downloadQue[]']:checked"), function() {
values.push($(this).val());
ajaxRequest($(this).val(),function(response){
console.log(response);
});
});
console.log(values);
return false;
});
this then calls a ajax function which i am trying to do a callback on.
function ajaxRequest(urlSend,callback){
var send = {
url: urlSend
}
$.ajax({
type: "POST",
url: "<?php echo base_url(); ?>index.php/upload",
data: send,
//dataType: "json",
//timeout: 8000,
beforeSend: function() {
},
success: function(response) {
callback('added');
},
error: function (response) {
callback('false');
}
});
}
this will then send to a php file.
function upload(){
$output = shell_exec("wget {$_POST['url']} 2>&1");
return true;
}
What i am trying to do is after the callback from one url which it has download fully then grab the next value from the array and download that url and so on until all the urls in the array are downloaded fully.
at the moment it just downloads the first value and then crashes because it doesn't restart the loop after a return value of true is returned.
Hope this makes sense to someone just looking for some help on the best way to loop through an array of values with a callback after complete.
May be this structure can help you. In this variant you go next URL only after successful completion of the previous Ajax call.
var arr = ['url0','url1','url2','url3'];
var index = 0;
function Run(){
DoAjax(arr[index]);
}
function Next( ){
if(arr.count = index-1)
{
index =0;
return;
}else{
DoAjax(arr[index ]);
}
}
function DoAjax(url){
$.ajax({
type: "POST",
url: url,
data: send,
beforeSend: function() {
},
success: function(response) {
index ++;
Next();
// Addition logic if needed
},
error: function (response) {
}
});
}
Run()
Now that I have a bit more time, I thought it would be good to show an alternative which takes advantage of the fact that jquery ajax is now implemented as a deferred. Meaning you can use pipe chaining to do all the work for you. I've also eliminated the callbacks by taking advantage of the deferred behavior.
This should give you the idea.
// Use jquery deferred pipe chaining to force
// async functions to run sequentially
var dfd = $.Deferred(),
dfdNext = dfd,
x,
values = [],
// The important thing to understand here is that
// you are returning the value of $.ajax to the caller.
// The caller will then get the promise from the deferred.
ajaxRequest = function (urlSend) {
var send = {
url: urlSend
}
return $.ajax({
type: "POST",
url: "<?php echo base_url(); ?>index.php/upload",
data: send,
});
};
// Starts things running. You should be able to put this anywhere
// in the script, including at the end and the code will work the same.
dfd.resolve();
// Deferred pipe chaining. This is the main part of the logic.
// What you want to note here is that a new ajax call will
// not start until the previous
// ajax call is completely finished.
// Also note that we've moved the code that would
// normally be in the callback.
// Finally notice how we are chaining the pipes by
// replacing dfdNext with the return value from the
// current pipe.
for (x = 1; x <= 4; x++) {
values.push(x);
dfdNext = dfdNext.pipe(function () {
var value = values.shift();
return requestAjax(value).
done(function(response) {
// Code here that you would have
// put in your callback.
console.log(response);
}).
fail(function(response) {
console.log(response);
};
});
}
Working example you can play with on jsFiddle.

Javascript value is returned from webservice but will not show unless a breakpoint is used

I have a javascript function that calls a web service. The data comeback (I see the Jason return in FireBug) the value is blank when I attempt to use it unless I set a break point. With a break point set the value can be used, without it is not available.
Here is a snippet of the offending call.
function getTheNote(noteCode){
var _myNote = "";
var theID = $('#CustNo').val();
var myDTO = { 'theID': theID, 'noteCode': noteCode, };
var toPass = JSON.stringify(myDTO);
$.ajax({
type: 'POST',
contentType: "application/json; charset=utf-8",
dataType: "json",
url: "AR_Cust_Mgt.aspx/getNote",
data: toPass,
success: function (data) {
_myNote = data.d;
}
});
//setTimeout(_myNote += _myNote, 120000);
//for(var x = 0; x < 200000; x++){}
//return _myNote;
alert(_myNote);
}
Originally I was sending the value back to a calling function the return statement is where I would set my break point and the data would be returned, without nothing. Now you can see I attempted to use an alert inside the function with the same results.
With a break point I get a value without I get nothing, I have even attempted to use some delays.
Please help.
The ajax call is asynchronous. Anything you want to do with the result needs to be in your anonymous function success: function(data) { ... or the anonymous function needs to call other functions to do stuff.
As it is coded now, $.ajax will be called, the script execution continues on before the ajax call returns.
small change, big difference: you are not calling alert IN the succes function
success: function (data) {
_myNote = data.d;
alert(_myNote);
}

Categories

Resources