{"id":80,"date":"2005-04-21T14:18:43","date_gmt":"2005-04-21T20:18:43","guid":{"rendered":"\/?p=80"},"modified":"2005-04-21T14:18:43","modified_gmt":"2005-04-21T20:18:43","slug":"ajax-gotchas","status":"publish","type":"post","link":"https:\/\/www.codedread.com\/blog\/archives\/2005\/04\/21\/ajax-gotchas\/","title":{"rendered":"Ajax Gotchas"},"content":{"rendered":"<p>This is just a quick entry for me to jot down some caveats that I encountered while making a simple instant messaging application for the browser using Asynchronous JavaScript, XML and PHP.  <!--more--><\/p>\n<h2>Properly Set the Content Type of the Returned Document<\/h2>\n<p>I stumbled around for a bit and couldn't figure out why the XML document returned by the PHP server script wasn't being parsed into walkable DOM objects at the client side by my JavaScript.  Finally it dawned on me that the client must receive the XML content type in the header.  I used the following PHP code (before any output):<\/p>\n<div class=\"code\">\nheader(\"Content-type: text\/xml\");\n<\/div>\n<p>And suddenly everything started parsing from the client side!\n<\/p>\n<div class=\"ads\"><object type=\"text\/html\" width=\"468\" height=\"60\" data=\"http:\/\/www.codedread.com\/gads.php\"><\/object><\/div>\n<h2>Preventing Browser Caching of the URL<\/h2>\n<p>When I finally got an XML document returned, I noticed that Internet Explorer would not retrieve a newer document from a subsequent request (though somehow Firefox was able to get a new XML document).  Once I determined that different browsers were experiencing different results, I had an inkling that it was a caching problem on the client-side.  When doing periodic \"get\" via the XMLHttpRequest document, apparently Internet Explorer was checking its cache and noticing that the same URL had been fetched previously and just using that stale document.  IE had no way of knowing that the retrieved document could by dynamic content that might vary over time.<\/p>\n<p>The way around this is to modify the URL slightly so that IE believes it is a new document.  I did this using the following JavaScript code:<\/p>\n<div class=\"code\">\nvar urlstr = \"myserver.php?<strong>RANDOM=\" + (Math.random() * Date.parse(new Date()))<\/strong> + rest of url...<br \/>\nvar req = new XMLHttpRequest(); \/\/ use ActiveXObject(\"Microsoft.XMLHTTP\") if IE<br \/>\nreq.open(\"GET\", urlstr, true);\n<\/div>\n<p>This inserts an (unused) URL variable into the string and fools the browser into thinking it is a new document (which, in fact, it is!).  I have no idea if this should be considered a bug from the IE side or the FF side...\n<\/p>\n<h2>PHP File Locking<\/h2>\n<p>Since my little application uses the server's filesystem for its backend storage (and not a database) and transactions can occur in parallel and asynchronously, I took some care to make sure I locked the server-side files before accessing them.  I used PHP's \"flock\" function:<\/p>\n<div class=\"code\">\n$f = @fopen($filename, 'w');<br \/>\n<strong>while( !flock($f, LOCK_EX) ) {<br \/>\n&#160;&#160;usleep(50000);<br \/>\n}<\/strong><br \/>\n$xmlstr = formatIntoXml(...);<br \/>\nfwrite($f, $xmlstr);<br \/>\nfwrite($f, \"rn\");<br \/>\n<strong>flock($f, LOCK_UN);<\/strong><br \/>\nfclose($f);\n<\/div>\n<p>Though I never experienced any odd conflict scenarios even before I implemented file locking (due to the relatively low network traffic that my app experiences), I'm convinced that this is a necessity for any real application (and a very persuasive argument to using a database as the backend storage mechanism).<\/p>\n<div class=\"ads\"><object type=\"text\/html\" width=\"468\" height=\"60\" data=\"http:\/\/www.codedread.com\/gads.php\"><\/object><\/div>\n","protected":false},"excerpt":{"rendered":"<p>This is just a quick entry for me to jot down some caveats that I encountered while making a simple instant messaging application for the browser using Asynchronous JavaScript, XML and PHP.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[31,38,42,25,11,14,28,30],"tags":[],"class_list":["post-80","post","type-post","status-publish","format-standard","hentry","category-ajax","category-javascript","category-php","category-software","category-technology","category-tips","category-web","category-xml"],"_links":{"self":[{"href":"https:\/\/www.codedread.com\/blog\/wp-json\/wp\/v2\/posts\/80","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.codedread.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.codedread.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.codedread.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.codedread.com\/blog\/wp-json\/wp\/v2\/comments?post=80"}],"version-history":[{"count":0,"href":"https:\/\/www.codedread.com\/blog\/wp-json\/wp\/v2\/posts\/80\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.codedread.com\/blog\/wp-json\/wp\/v2\/media?parent=80"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.codedread.com\/blog\/wp-json\/wp\/v2\/categories?post=80"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.codedread.com\/blog\/wp-json\/wp\/v2\/tags?post=80"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}