This is my first post on stackoverflow, and it concerns a problem I'm having while trying to learn the basics of Ajax.
This is the scenario:
I have created an HTML file with an embedded script
The script ...
- creates an XMLHttpRequest object
- invokes open() to assign the HTTP method and URL
- assigns the event handler to the onreadystatechange
property
- sends the request
What is the request?
The request is simply going to the local web server (Apache) on the same host to run a php script. The php script creates an XML file, and populates the file with a single value, which is the time on the server.
What does the client do with the response?
The event handler uses DOM to extract the time value from the XML and inserts it as the innerHTML in a div element.
What's not working?
Actually it works fine in IE8, but I can't get it to work in Firefox!
What does work, and what doesn't?
The request is being sent, and the event handler is indeed being invoked, both in IE8 and in Firefox. Whereas IE8 populates the div on the web page beautifully, in Firefox the XMLHttpRequest object appears to be empty; that is to say, the readyState is being updated but there are no reponse headers or text, and no status or status text.
What I have done to investigate
- I have reviewed the MDN documentation for XMLHttpRequest to see whether I'm doing something wrong, but my code appears ok.
- I have populated the script with lots of alerts statements to try to debug this, but I can find only the symptoms, not the cause.
- I have downloaded and installed Fiddler to examine the request and responses: I can confirm that the requests are being sent from both IE8 and Firefox, and (not only that) that the web server is returning the EXACT same responses to both browsers - headers and body.
So the question is:
Why is this not working? Ajax is no longer a new technology and if it works ok in IE8 (6 years old) then surely Firefox 31 (1 year old) should have no problem.
Here is my server request code:
function getServerTime()
{
if (http)
{
var url;
var userAgent = window.navigator.userAgent
var msie = userAgent.indexOf("MSIE") >= 0;
var msieVerNum;
if (msie)
{
/* The string "MSIE" has been found so this script
* is running under Internet Explorer. */
//Remove the portion of the user agent string to the left of "MSIE ".
userAgent = userAgent.substring(userAgent.indexOf("MSIE "));
/* Remove "MSIE " from the user agent string thus leaving the
* version number at the start of the string. */
userAgent = userAgent.replace("MSIE ","");
msieVerNum = parseInt(userAgent);
if (msieVerNum <= 8)
{
/* This script is running under Internet Explorer 8 or older.
* Hence, using the Date.getTime() function.
*/
url = "http://localhost./telltimeXML.php?" + (new Date()).getTime();
}
}
if (! msie || msieVerNum >= 9)
{
if (Date.now)
{
url = "http://localhost./telltimeXML.php?" + Date.now();
}
}
if (typeof(url) != "undefined")
{
http.open("GET", url, true);
http.onreadystatechange = useHttpResponse;
//http.send(null);
http.send();
}
}
else
{
alert("no XMLHttpRequest object");
}
}
...and here is my event handler:
function useHttpResponse()
{
if (http.readyState == 4)
{
if (http.status == 200)
{
document.getElementById("ShowTime").innerHTML =
http.responseXML.getElementsByTagName("timenow")[0].childNodes[0].nodeValue;
}
}
else
{
document.getElementById("ShowTime").innerHTML = "<img src=\"0002.gif\" />";
}
}
Related
I have searched in this forum for quiet a bit and here's my problem -
I have a ng-repeat in my html which takes in a list of messages(Json object).
Each message JSON has a sender email address - e.g. abc#gmail.com
Now, I have to get the email address from the message and form another REST API request to fetch their images for e.g. - http://<>:8080/getImage/abc#gmail.com (email address dynamic)
So in my code, I'll have a ng-repeat and a ng-src pointing to the image REST URL
If there's no image in server, it returns a 404 and displays a broken image on the UI. How do I handle it? On the other hand, if I make a http request to determine if there's a success message and on failure return a default image, then the whole thing goes through an endless loop. I'll try to create a fiddle and include it for better explanation.
Use the error block to handle such behavior:
function($http) {
var restUrl = 'getImage/abc';
return {
fetchImage: function(imageId) {
var self = this;
return $http.get(restUrl + '/' + imageId).
success(function(data) {
return self.imageUrl = data;
}).
error(function(data) {
return self.imageUrl = "pathToDefaultImage";
});
},
...
I have a small repo factory service that I am using in my controller:
My Controller:
angular.module('repoApp')
.controller('MainCtrl', function ($scope, $repoService) {
$scope.repos = $repoService.getRepos();
});
My Factory:
angular.module('repoApp')
.factory('$repoService', function ($http) {
var repos =
// $http.defaults.headers['If-Modified-Since'] = 'Sat, 01 Jun 2013 1:31:30 GMT';
$http.jsonp('https://api.github.com/repos/mojombo/jekyll/issues?state=closed&callback=JSON_CALLBACK',
{
cache: true
}
);
// Public API here
return {
getRepos: function () {
return repos.then(function(repoData) {
return repoData.data.data;
});
}
};
});
This works fine - I get back the results but every time the browser refreshes, I end up getting a 200 response instead of a 304. What am I doing wrong?
I have also tried using JSON_SINGLE_CALLBACK as mentioned in this closed issue.
You're not actually using the GitHub method of checking for a modified set of issues. You have it commented out but I'm not sure the list of issues actually return (or work with) the Last-Modified/If-Modified-Since headers. It should return an ETag header which you can then send back using If-None-Match. Otherwise, I might guess that angular is only going to cache for the single page load and that if you added a way of testing (without refreshing the page in the browser) this, e.g., a button to re-issue this request, you might see angular cache the request.
Then again you should check the documentation to see if you should be expecting a 200 (the original response) or a 304 (a faked response). You should also check the headers on the response to see if your ratelimit changes.
I started learning AJAX recently and am trying a very simple project which involves capturing some form data and sending it to two servers.
The first server is the one which hosts the website and server side php handling. This worls fine
The second server is a python basic http server which handles only the POST operation request send from AJAX. This functionality works but is a bit weird.
Let me explain
Here is my AJAX code which is absolutely straight forward.
function xml_http_post(url, data) {
var req = false;
try {
// Firefox, Opera 8.0+, Safari
req = new XMLHttpRequest();
}
catch (e) {
// Internet Explorer
try {
req = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
req = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {
alert("Your browser does not support AJAX!");
return false;
}
}
}
req.onreadystatechange = function() {
if (req.readyState == 4) {
// callback(req);
}
}
req.open("POST", url, true);
req.setRequestHeader("Content-type","text/plain");
req.send(data);
}
Since I do not intend to send back any response , my callback function on ready state change is empty.
But when I execute this code ( triggered by onclick on a button) , the POST doesnt work and server doesnt seem to receive anything.
But the most surprising thing is that if I keep a breakpoint at req.open( ) and then do a manual step execution then it works always. Which means , I guess that there is some timing issue which needs to be resolved.
It works fine without breakpoints if the third parameter "async" is set to false but that is anyway undesirable so I want to make it work with async = true.
Any help would be greatly appreciated.
Thanks
Shyam
As I figured out, the form page was getting unloaded by a php script which was invoked as a action of the form b the first server. This resulted in the javascript code being partially or not executed.
So I figured out that sync XHR is the only way for my.
I am a programmer on an MVC/ajax project that receives significant traffic from its customers. We've been seeing one or two isolated instances (per day) of a controller action not receiving parameters from the client.
Long story short: the actions are being called via jQuery ajax, and the action params are only null if the ajax call is made while the browser is navigating to another page. IE click a link and then trigger an ajax call.
I added some crude validation around these calls to ensure that we aren't actually passing nulls in the ajax data, and this hasn't alleviated the problem. An example of one of the calls is below.
var searchValue = _txtSearch.val().trim();
if (searchValue === null
|| searchValue === undefined
|| searchValue.length < _minimumLengthForSearch) {
_txtSearch.focus();
return;
}
// clear out the value when launching
_txtSearch.val('');
$.post(_quickSearchUrl,
{ searchString: searchValue },
function (data) {...},
"json");
I found an old IEBlog post that suggests IE might handle this situation differently from other browsers. I was curious as to whether anyone else has encountered this phenomena before. Again, I can only reproduce this issue in IE and only during page navigation.
Edit: It is difficult to reproduce this exception with Fiddler active for some reason, but when I manage to Fiddler displays the following error message:
Fiddler has detected a protocol violation in session #4.
Content-Length mismatch: Request Header indicated 24 bytes, but client sent 0 bytes.
Using Fiddler, I was able to reproduce this in a very rare instance and realized that it can be treated as a content length mismatch (that is the error message that fiddler displays when it occurs). Specifically, on the server side the request content length will not match the actual Form/InputStream contents. We overrode OnAuthorization to manually detect and handle this case.
protected override void OnAuthorization(AuthorizationContext filterContext)
{
//Detect IE missing post data phenomenon
var request = HttpContext.Request;
if (request.IsAjaxRequest() == true && request.ContentLength > 0
&& request.Form.HasKeys() == false && request.InputStream.Length == 0)
{
throw new ContentLengthMismatchException(string.Format("Content Length Mismatch in URL: {0}", request.Url));
}
base.OnAuthorization(filterContext);
}
I have an aspx page on which I am using XDomainRequest object to populate two div(s) with html returned from AJAX response.
I have used Jquery to get the divs and perform "each()" on the retrieved List
var divs = $("div");
divs.each(function(index) {
if (window.XDomainRequest) {
xdr = new XDomainRequest();
if (xdr) {
xdr.onload = function() {
alert("XDR Response - " + xdr.responseText);
var currentDivID = divs[index].attributes["id"].value;
var selectedDiv = $("div[id='" + currentDivID + "']");
if (xdr.responseText == '') selectedDiv.attr("style", "display:none;");
else selectedDiv.append(xdr.responseText);
};
xdr.open("GET", xdrUrl);
try {
xdr.send();
} catch (e) {
alert(e);
}
} else {
alert('Create XDR failed.');
}
} else {
alert('XDR not found on window object .');
}
}
Now, whats happening is , i have two Divs on a page that have different IDs and when this code runs on "$.ready(function(){})" , both requests are asynchronously sent to the server and processed
the result is
1. sometimes the onload get the response for the second div in both div results.
2. IE sents only one request to the server(I am using fiddler to see what requests are sent to server).
Can anybody guide me whats wrong with the code ? As far as I know XDR does not support synchronous calls, and asynchronous calls are giving me wrong results. Any workaround/tip for this problem.
Issue solved by myself when I pointed out a mistake in my code:(.
xdr = new XDomainRequest();
should be
var xdr = new XDomainRequest();
For Point 2 , I added "Cache-Control:no-cache" header in my response and it solved the matter.