Unexpected JavaScript Actions reported by my Users - javascript

My users keep complaining that a link does not show up for them. For me, I have tested this on several browsers and it works for me.
What should happen is that a process is started via AJAX using JQuery and once that is done I keep checking with the server via AJAX how much of the process has been done and once the process is complete I show them a link. But a lot of users tell me that it shows them the link and it quickly disappears back to showing 100.0%!
I can't see how I can fix this and I was hoping you guys could help me write something fool proof so that the link is always shown!
Here is the code concerned (its been shortened).
var startTime;
var continueTime;
var done = false;
function convertNow(validURL){
startTime = setTimeout('getStatus();', 6000);
$.ajax({
type: "GET",
url: "main.php",
data: 'url=' + validURL + '&filename=' + fileNameTxt,
success: function(msg){
done = true;
$("#loading").hide("slow");
$("#done").html("LINK SHOWN HERE");
}//function
});//ajax
}//function convertNow
function getStatus()
{
if(done==false){
$.ajax({
type: "POST",
url: "fileReader.php",
data: 'textFile=' + fileNameTxt,
success: function(respomse){
textFileResponse = respomse.split(" ");
$("#done").html("PROGRESS SHOWN HERE IN PERCENTAGES");
}
});//ajax
continueTime = setTimeout('getStatus();', 3000);
}
}
Thanks all
P.S. I have this question before and was given an idea of using a conditional in the function but that didn't work when it should have!!
UPDATE
I have some of my users what OS and browsers they are using and they usually say a Mac Os and firefox or safari. Not sure if that help with the solution.

The behaviour described by the users suggests that the success callback of your getStatus function is called after the one in convertNow. You should test done variable in this callback
function getStatus(){
if(done==false){
$.ajax({
type: "POST",
url: "fileReader.php",
data: 'textFile=' + fileNameTxt,
success: function(respomse){
// FIX : Already done, just ignore this callback
if (done) return;
textFileResponse = respomse.split(" ");
$("#done").html("PROGRESS SHOWN HERE IN PERCENTAGES");
// BONUS : call getStatus only when previous ajax call is finished
continueTime = setTimeout('getStatus();', 3000);
}
});//ajax
}
}
EDIT : This solution should prevent the bug from appearing most of the time, but there is still a chance. The only way to be sure is to remove the callback from convertNow and let the one in getStatus set the link when the processing is done (don't forget to allow only one call to getStatus at a time, see "BONUS" modification above).

If done is never set back to false then the reported behavior would be expected upon the second call to convertNow.
Since the ajax call in convertNow uses GET instead of POST, it is possible that a browser is returning a cached result whenever parameters are identical to a previous call.

Related

Put ajax response attribute in to a variable for Google Books cover image

I am trying to put a url from an ajax response into a variable in jquery.
I have written the following code:
var thumb = $.ajax({
dataType: 'json',
url: 'https://www.googleapis.com/books/v1/volumes?q=isbn:' + isbn,
success: function(response){
return $(response).volumeInfo.imageLinks.thumbnail;
}}).responseText;
It was my understanding from looking at other answers that I must add .responseText at the end, or the code will continue without waiting for the ajax response.
However, thumb variable remains undefined.
I tried implementing the following solution with relevant changes (As I am passing only one ISBN at a time, there shouldn't be an array. The response should contain only one imageLinks.thumbnail url), but I cannot seem to catch the response correctly.
I looked into other answers, especially this one, but I am still not clear about how to reach the ajax response.
$.ajax is asynchronous, meaning the code will execute completely and the success callback will be fired at a later time.
var thumb is evaluated immediately. Do some reading on "callbacks" and "promises" to get more familiar with this topic.
A solution to your issue is:
function setThumbnail(thumbnail){
// this will evaluate later, when the ajax returns success
console.log('thumbnail gotten!');
var thumb = thumbnail; // do something with in in this function
}
$.ajax({
dataType: 'json',
url: 'https://www.googleapis.com/books/v1/volumes?q=isbn:' + isbn,
success: function(response){
setThumbnail($(response).volumeInfo.imageLinks.thumbnail);
}
});
// This line will evaluate immediately and carry on
console.log('ajax executed');
I threw in some logs for you to help you understand the order of execution here.
I would also note that $(response) looks odd to me, without testing it I think it should probably be just response.volumeInfo....
console.log(response) in the success callback to make sure you understand what data you are getting back.

JQuery - Looping a .load() inside a 'for' statement

I'm not sure if this will actually be possible, since load() is an asynchronous method, but I need some way to basically Load several little bits of pages, one at a time, get some data included in them via JavaScript, and then send that over via Ajax so I can put it on a database I made.
Basically I get this from my page, where all the links I'll be having to iterate through are located:
var digiList = $('.2u');
var link;
for(var i=0;i<digiList.length;i++){
link = "http://www.digimon-heroes.com" + $(digiList).eq(i).find('map').children().attr('href');
So far so good.
Now, I'm going to have to load each link (only a specific div of the full page, not the whole thing) into a div I have somewhere around my page, so that I can get some data via JQuery:
var contentURI= link + ' div.row:nth-child(2)';
$('#single').load('grabber.php?url='+ contentURI,function(){
///////////// And I do a bunch of JQuery stuff here, and save stuff into an object
///////////// Aaaand then I call up an ajax request.
$.ajax({
url: 'insertDigi.php',
type: 'POST',
data: {digimon: JSON.stringify(digimon)},
dataType: 'json',
success: function(msg){
console.log(msg);
}
////////This calls up a script that handles everything and makes an insert into my database.
}); //END ajax
}); //END load callback Function
} //END 'for' Statement.
alert('Inserted!');
Naturally, as would be expected, the loading takes too long, and the rest of the for statement just keeps going through, not really caring about letting the load finish up it's business, since the load is asynchronous. The alert('Inserted!'); is called before I even get the chance to load the very first page. This, in turn, means that I only get to load the stuff into my div before I can even treat it's information and send it over to my script.
So my question is: Is there some creative way to do this in such a manner that I could iterate through multiple links, load them, do my business with them, and be done with it? And if not, is there a synchronous alternative to load, that could produce roughly the same effect? I know that it would probably block up my page completely, but I'd be fine with it, since the page does not require any input from me.
Hopefully I explained everything with the necessary detail, and hopefully you guys can help me out with this. Thanks!
You probably want a recursive function, that waits for one iteration, before going to the next iteration etc.
(function recursive(i) {
var digiList = $('.2u');
var link = digiList.eq(i).find('map').children().attr('href') + ' div.row:nth-child(2)';
$.ajax({
url: 'grabber.php',
data: {
url: link
}
}).done(function(data) {
// do stuff with "data"
$.ajax({
url: 'insertDigi.php',
type: 'POST',
data: {
digimon: digimon
},
dataType: 'json'
}).done(function(msg) {
console.log(msg);
if (i < digiList.length) {
recursive(++i); // do the next one ... when this is one is done
}
});
});
})(0);
Just in case you want them to run together you can use closure to preserve each number in the loop
for (var i = 0; i < digiList.length; i++) {
(function(num) { < // num here as the argument is actually i
var link = "http://www.digimon-heroes.com" + $(digiList).eq(num).find('map').children().attr('href');
var contentURI= link + ' div.row:nth-child(2)';
$('#single').load('grabber.php?url=' + contentURI, function() {
///////////// And I do a bunch of JQuery stuff here, and save stuff into an object
///////////// Aaaand then I call up an ajax request.
$.ajax({
url: 'insertDigi.php',
type: 'POST',
data: {
digimon: JSON.stringify(digimon)
},
dataType: 'json',
success: function(msg) {
console.log(msg);
}
////////This calls up a script that handles everything and makes an insert into my database.
}); //END ajax
}); //END load callback Function
})(i);// <-- pass in the number from the loop
}
You can always use synchronous ajax, but there's no good reason for it.
If you know the number of documents you need to download (you can count them or just hardcode if it's constant), you could run some callback function on success and if everything is done, then proceed with logic that need all documents.
To make it even better you could just trigger an event (on document or any other object) when everything is downloaded (e.x. "downloads_done") and listen on this even to make what you need to make.
But all above is for case you need to do something when all is done. However I'm not sure if I understood your question correctly (just read this again).
If you want to download something -> do something with data -> download another thing -> do something again...
Then you can also use javascript waterfall (library or build your own) to make it simple and easy to use. On waterfall you define what should happen when async function is done, one by one.

jQuery check if url responsing

First of all I've read this question which I found very usefull.
I'm trying to detect if an url is responding. If so then use this url and start another function if false then create a new url and start an other function.
I tried to implement the code from the question mentioned above but I found it difficult to incorporate that in my code since I do not understand what he tries to mention with the callback.
So what I have is two functions:
function relatedProducts(relatedUrl){
$.getJSON(relatedUrl, function(data){
......
});
}
function liveSearch(liveSearchUrl){
$.getJSON(liveSearchUrl, function(data){
......
});
}
Further I have an variable url and I'm trying to test if that url is responding so not if it is valid.
var url ='apple/i-phone/iphone5';
function urlExists(url, exists){
$.ajax({
type: 'HEAD',
url: url,
success: function(){
// what do I have to do here???
Poster is mentioning `callback` but which one??
},
error: function(){
// what do I have to do here???
Poster is mentioning `callback` but which one??
}
});
}
urlExists(url, function(exists){
if(true){
var relatedUrl = ??
relatedProducts(relatedUrl);
} else {
var liveSearchUrl = ??
liveSearch(liveSearchUrl);
});
I'm still learning jQuery and I'm pretty confused by the poster and his answer ;)
Any help greatly appreciated.
AJAX is asynchronous and so calls to AJAX methods are non-blocking. So you can't expect any results from an AJAX method to be available when the control flow is returned to the caller and subsequent function calls should not rely on the AJAX call having completed.
Simple example:
doSomeStuff($.ajax(...)); //doesn't work
Other example:
var x = false;
$.ajax({
url: url,
success: function(){
x = true;
}
});
if (x) {
// probably doesn't work
}
That's where the callback functions come in: You can tell a call to an AJAX method to do some stuff once it is finished. Those are the success and error parameters in your example.
Now for your specific example. I realize you copied most of it from an answer to a similar question, but I see several problems with it, amongst other things your use of if (true), which is not what you want there, so here's my shot at improving that code:
First, we need 2 callbacks instead of one, there's no need to force one method to do what was clearly intended to be handled by 2 different methods.
var successCallback = function() {
var relatedUrl = '' // see note below code block
relatedProducts(relatedUrl);
}
var errorCallback = function() {
var liveSearchUrl = ''// see note below code block
liveSearch(liveSearchUrl);
}
Next, let's change your urlExists
function urlExists(url, sCallb, eCallb){
$.ajax({
type: 'HEAD',
url: url,
success: sCallb,
error: eCallb
});
}
And finally, this is how you put those pieces together:
var url ='apple/i-phone/iphone5';
urlExists(url,successCallback,errorCallback);
Some notes:
If you want relatedUrl and liveSearchUrl to be the same URL that was used for the ajax call, let me know and I'll change my example accordingly. If not, just put the url you want to use inside the quotes.
Of course, urlExists is a wrapper that's not even needed, you could use your url and the callbacks directly in the AJAX call, but this way it's much cleaner to look at, easier to understand and far more reusable.
This code will execute errorCallback for ANY error, and successCallback if no error occurred. This may actually not be what you want, especially if you consider that AFAIK 3xx status codes are considered an error. To get much finer control, you can define callbacks for each status code, or just for some of them, if you want I can update my example, let me know.
Please check this.It same like nob.
var callback = function (x){
if(x)
alert ("You can make real call to this url");
else
alert ("Somthing worng");
};
$.ajax({
type: 'HEAD',
url: "/echo/json",
success: function() {
callback(true);
},
error: function() {
callback(false);
}
});
http://jsfiddle.net/PK76X/152/
Callback is nothing but the value returned by a function.
When OP states callback, in the explanation of ans, he is referencing the address of return value.
For example: In var a = '10' a is the address and 10 is the value stored in it.
Now consider a function b() which returns some value:
function b(){
var a ='a';
return a;
}
var something = b(); // here **something** can be seen as callback of b()
Now coming to your point when OP uses the word callback in this code he is referring nothing but a variable. You can replace the word callback with any work like test, abc and it will still produce the same result.
Hope this helps

Using JavaScript setInterval function

I found out a lot of questions related to using of JavaScript setInterval() function and found the answers and also implemented them, but my hard luck, none could gain success. I might be doing some silly mistake, but i am not able to find it out now. Following is my code snippet.
$.ajax({
url: "https://api.dropbox.com/1/oauth/request_token",
data:`{"oauth_version":"1.0","oauth_signature_method":"PLAINTEXT","oauth_consumer_key":"consumer_key","oauth_signature":"signature&"}`,
type: 'POST',
async: false,
cache: false,
dataType: 'text',
contentType: "application/x-www-form-urlencoded",
processData: true,
success: function(requestInfo)
{
console.log("requestInfo: "+requestInfo);
requestInfo = "http://localhost/?"+requestInfo;
var oauth_request_token = processQueryStringData(requestInfo, 'oauth_token'); //a regex function that parses oauth_token from requestInfo
var oauth_request_token_secret = processQueryStringData(requestInfo, 'oauth_token_secret');//a regex function that parses oauth_token_secret from requestInfo
console.log("oauth_token_secret: "+oauth_request_token_secret);
console.log("oauth_request_token: "+oauth_request_token);
var url = "<url-to-redirect to dropbox alongwith callback url>";
var win = window.open(url, 'DropBox Auth', 'width=800, height=600');
var pollTimer = window.setInterval(function() {
try {
console.log("URL ===== : " + win.document.URL);
if(**some condition is true**)
{
window.clearInterval(pollTimer);
// some code that i need to execute to get the authorize token and then the access tokens.
}
}
catch(e)
{
}
}, 1000);
});
The ajax returns a success and i get the oauth_request_token and oauth_request_token_secret. Also dropbox log-in page opens in a child window. But the setInterval is not executed since i dont see the console.log("URL ===== : " + win.document.URL); on the console.
Also, after reading a few answers, i created a function named event in which i placed the code from within the setInterval callback function and called that function like,
var pollTimer = window.setInterval(event,1000);
At this time,pollTimer is global.Also, i saw the log statement only once and then the html page was refreshed. I am not able to understand where i am going wrong. Might happen to be a silly mistake, but not able to figure it out. Help please.
Note: This code lies in a function present inside a .js file which is included in a html file.
Here is the thing. When you run function in setInterval, It is totally different context even if you call setInterval in ajax method. So I recommend to you to do check *some condition is true* statement first.

jQuery Ajax HTTP Request INTO a click function - not working

My question is:
Is it possible to do an Ajax request WITHIN a click function, with jQuery? (see example below), If so, what am I doing wrong? Because I'm not being able to do any request (I'm alerting the data through my success function and nothing is being retrieved).
Thank you very much in advance for any help! :)
function tracker(){
this.saveEntry = function(elementTracked, elementTrackedType){
var mode = "save";
var dataPost = "mode="+mode+"&elementTracked="+elementTracked+"&elementTrackedType="+elementTrackedType;
$.ajax({
type: "POST",
url: 'myURL',
data:dataPost,
success:function(msg){
alert(msg);
},
beforeSend:function(msg){
$("#trackingStatistics").html("Loading...");
}
});
return;
},
this.stopLinksSaveAndContinue = function(){
var fileName;
$("a[rel^='presentation']").click(function(e){
fileName = $(this).attr("rel").substring(13);
this.saveEntry(fileName,"Presentation");
})
}
}
If your anchor is linked with the href attribute, then this may be interrupting your AJAX request. A similar problem was recently discussed in the following Stack Overflow post:
window.location change fails AJAX call
If you really want to stick to using AJAX for link tracking, you may want to do the following:
Link
With the following JavaScript logic:
function tracker(url) {
$.ajax({
type: 'POST',
url: 'tracker_service.php',
data: 'some_argument=value',
success: function(msg) {
window.location = url;
}
});
}
Have you considered the possiblity that the request might be failing. If so, you're never going to hit the alert.
Can you confirm that the beforeSend callback is being fired?
Also, I'm assuming 'myURL' isn't that in your real-world source code?
There may also be something awry in the }, that closes your function.
Im guessing some sort of error is being generated. Try adding
error:function(a,b){
alert(a);
},
After 'success'

Categories

Resources