{"push_id":887562493,"size":6,"distinct_size":6,"ref":"refs/heads/Chp_13AdvancedAjax","head":"87ea4aae202e3fe6fd11d2d14790f5f97e69f524","before":"be3768f13bbb5ea36e2d64637bb24619d454873f","commits":[{"sha":"4c185e55f1b3bfc35372ab4815b2d14c689f6b08","author":{"email":"688085edcac35a6f5d4cd9ba4db0e893cb0d2736@gmail.com","name":"petrero"},"message":"Introducing any kind of network interaction into an application brings along some degree of uncertainty. The user's connection could drop in the middle of an operation or a temporary server issue could interrupt communications. Because of these reliability concerns, we should always plan for the worst case and prepare for error scenarios.\n  The jQuery.ajax() function can take a callback function named error to be called in these situations. In this callback, we should provide some kind of feedback to the user indicating that an error has occurred.\n  The error callback can be triggered for a number of reasons. Among these are:\n• The server returned an error status code, such as 403 Forbidden, 404 Not Found, or 500 Internal Server Error.\n• The server returned a redirection status code, such as 301 Moved Permanently. An exception is 304 Not Modified, which does not trigger an error because the browser can handle this condition correctly.\n• The data returned by the server could not be parsed as specified (for example, it is not valid JSON data when dataType is json ).\n• The .abort() method is called on the XMLHttpRequest object.\n  Detecting and responding to these conditions is important in providing the best possible user experience. We saw in Chapter 6, Sending Data with Ajax, that the error code, if any, is provided to us in the .status property of the jqXHR object that is passed to the error callback. We can use the value of jqXHR.status to react differently to different kinds of errors if that is appropriate.","distinct":true,"url":"https://api.github.com/repos/pyterDiaconescu/jQuery/commits/4c185e55f1b3bfc35372ab4815b2d14c689f6b08"},{"sha":"dc9ec9687a719d52a74ea4ce26f55917c3f30d24","author":{"email":"688085edcac35a6f5d4cd9ba4db0e893cb0d2736@gmail.com","name":"petrero"},"message":"However, the server errors are only useful when they are actually observed. Some errors are immediately detected, but other conditions can cause a long delay between the request and eventual error response.\n  When a reliable server timeout mechanism is not available, we can enforce our own client-side request timeout. By providing a time in milliseconds to the timeout option, we tell $.ajax() to trigger .abort() on its own if that amount of timeelapses before a response is received.\n  With the timeout in place, we can be assured that within 15 seconds either the data will be loaded or the user will receive an error message.","distinct":true,"url":"https://api.github.com/repos/pyterDiaconescu/jQuery/commits/dc9ec9687a719d52a74ea4ce26f55917c3f30d24"},{"sha":"36795b8a2706fb78ac5f37fbd995e7e451a30e61","author":{"email":"688085edcac35a6f5d4cd9ba4db0e893cb0d2736@gmail.com","name":"petrero"},"message":"When an Ajax request is made, jQuery determines the best mechanism available for retrieving the data. This transport could be the standard XMLHttpRequest object, the Microsoft ActiveX XMLHTTP object or a <script> tag.\n  Because the transport used can vary from request to request, we need a common interface in order to interact with the communication. The jqXHR object provides this interface for us: it is a wrapper for the XMLHttpRequest object when that transport is used, and in other cases, it simulates XMLHttpRequest as best it can. Among the properties and methods it exposes are:\n• .responseText or .responseXML containing the returned data\n• .status and .statusText containing a status code and description\n• .setRequestHeader() to manipulate the HTTP headers sent with the request\n• .abort() to prematurely halt the transaction\n  This jqXHR object is returned from all the jQuery's Ajax methods, so we can store the result if we need access to any of these properties or methods.\n  Perhaps a more important aspect of jqXHR than the XMLHttpRequest interface, however, is that it also acts as a promise. In Chapter 11, Advanced Effects, we learned about deferred objects, which allow us to set callbacks to be fired when certain operations complete. An Ajax call is an example of such operation, and the jqXHR object provides the methods we expect from a deferred object's promise.\n  Using the promise's methods, we can rewrite our jQuery.ajax() call to replace the success and error callbacks with an alternate syntax.\n  At first glance, calling .done() and .fail() doesn't seem any more useful than the callback syntax we used previously. However, the promise methods offer several advantages. First, the methods can be called multiple times to add more than one handler if desired. Second, if we store the result of the jQuery.ajax() call in a variable, we can attach the handlers later if that makes our code structure more readable. Third, the handlers will be invoked immediately if the Ajax operation is already complete when they are attached. Finally, we should not discount the readability advantage of using a syntax that is consistent with other parts of the jQuery library.","distinct":true,"url":"https://api.github.com/repos/pyterDiaconescu/jQuery/commits/36795b8a2706fb78ac5f37fbd995e7e451a30e61"},{"sha":"2f626f14a3b17e6c874e4604fb2a82fb39b98c66","author":{"email":"688085edcac35a6f5d4cd9ba4db0e893cb0d2736@gmail.com","name":"petrero"},"message":"As another example of using the promise methods, we can add a loading indicator when a request is made. Since we want to hide the indicator when the request completes successfully or otherwise, the .always() method will come in handy.\n  Before we issue the jQuery.ajax() call, we add the loading class to the response container. Once the load is complete, we remove it again. In this way, we have further enhanced the user experience.\n  To really get a grasp of how the promise behavior can help us, though, we need to look at what we can do if we store the result of our jQuery.ajax() call in a variable for later use.","distinct":true,"url":"https://api.github.com/repos/pyterDiaconescu/jQuery/commits/2f626f14a3b17e6c874e4604fb2a82fb39b98c66"},{"sha":"b2eb44dc6b8bdadb6557c0896d2803ce1a08e733","author":{"email":"688085edcac35a6f5d4cd9ba4db0e893cb0d2736@gmail.com","name":"petrero"},"message":"If we need to use the same piece of data repeatedly, it is wasteful to make an Ajax request each time. To prevent this, we can cache the returned data in a variable. When we need to use some data, we can check to see if the data is already in the cache. If so, we act on this data. If not, we need to make an Ajax request, and in its .done() handler, we store the data in the cache and act on the returned data.\n  We've introduced a new variable named api to hold the jqXHR objects we create. This variable is an object with keys corresponding to the searches being performed. When the form is submitted, we look to see if there is already a jqXHR object stored for that key. If not, we do the query as before, storing the resulting object inside api .\n  The .done() , .fail() , and .always() handlers are then attached to the jqXHR object. Note that this happens regardless of whether an Ajax request was made. There are two possible situations to consider here.\n  First, the Ajax request might be sent if it hasn't before. This is just like the previous behavior: the request is issued and we use the promise methods to attach handlers to the jqXHR object. When a response comes back from the server, the appropriate callbacks are fired and the result is printed to the screen.\n  On the other hand, if we have performed this search in the past, the jqXHR object is already stored in api . In this case, no new search is performed, but we still call the promise methods on the stored object. This attaches new handlers to the object, but since the deferred object has already been resolved, the relevant handlers are fired immediately.\n  The jQuery deferred object system handles all the hard work for us. With a couple of lines of code, we have eliminated duplicated network requests from the application.","distinct":true,"url":"https://api.github.com/repos/pyterDiaconescu/jQuery/commits/b2eb44dc6b8bdadb6557c0896d2803ce1a08e733"},{"sha":"87ea4aae202e3fe6fd11d2d14790f5f97e69f524","author":{"email":"688085edcac35a6f5d4cd9ba4db0e893cb0d2736@gmail.com","name":"petrero"},"message":"An increasingly common feature of searches is to display a dynamic list of results as the user is typing. We can emulate this 'live search' feature for our jQuery API search by binding a handler to the keyup event.\n  Here, we simply trigger the form's submit handler whenever the user types something in the Search field. This could have the effect of sending many requests across the network in rapid succession, depending on the speed at which the user types. This behavior could bog down JavaScript's performance; it could clog the network connection, and the server might not be able to handle that kind of demand.\n  We're already limiting the number of requests with the request caching that we've just put in place. We can further ease the burden on the server, however, by throttling the requests. In Chapter 10, Advanced Events, we introduced the concept of throttling when we created a special throttledScroll event to reduce the number of times the native scroll event is fired. In this case, we want to make a similar reduction in activity; this time with the keyup event.\n  Our technique here, sometimes referred to as debouncing, is a bit different from the one we used in Chapter 10, Advanced Events. Whereas in that example we needed our scroll handler to take effect multiple times as scrolling continued; here we only need the keyup behavior to happen one time after typing has ceased. To do this, we keep track of a JavaScript timer that starts whenever the user presses a key. Each keystroke resets that timer, so only once the user stops typing for the designated amount of time (300 milliseconds) does the submit handler get triggered and the Ajax request performed.","distinct":true,"url":"https://api.github.com/repos/pyterDiaconescu/jQuery/commits/87ea4aae202e3fe6fd11d2d14790f5f97e69f524"}]}