(bug 41342) jquery.suggestions: Call cancel before fetching.
authorMatmaRex <matma.rex@gmail.com>
Sun, 9 Dec 2012 20:08:49 +0000 (21:08 +0100)
committerTimo Tijhof <ttijhof@wikimedia.org>
Sun, 16 Dec 2012 20:34:37 +0000 (21:34 +0100)
This caused race conditions in the calling code, if it used AJAX
and they completed in different order than they were started.

For example in mediawiki.searchSuggest, when one slowly types
"wikipedia", 9 requests get sent (suggestions for "w", "wi",
"wik", etc.), but they might not necessarily arrive in the same
order, especially on slow (e.g. mobile) connections.

Then you get the race condition effect - suggestions for
"wikipedia" flash briefly and then are replaced by suggestions for
"wik", even though the bolding is correct.

This commit fixes the issue by using a function that was already
present, that calls the callback as well as clearing the internal
timeout, which for some reason wasn't used in this code path.

Change-Id: I880a61e5e45a64bea6d679ed160c4be3da085dfa

RELEASE-NOTES-1.21
resources/jquery/jquery.suggestions.js

index 78ef1df..f2cfbb7 100644 (file)
@@ -112,6 +112,8 @@ production.
   <h4>, <h5> or <h6> to only <h3>s, with a <h2> hidden heading above them.
   If you are styling or scripting the headings in a custom way, this change
   will require updates to your site's CSS or JS.
+* (bug 41342) jquery.suggestions should cancel any active (async) fetches
+  before it triggers another fetch.
 
 === API changes in 1.21 ===
 * prop=revisions can now report the contentmodel and contentformat.
index edc18a7..ac579db 100644 (file)
@@ -49,8 +49,8 @@
 
 $.suggestions = {
        /**
-        * Cancel any delayed updateSuggestions() call and inform the user so
-        * they can cancel their result fetching if they use AJAX or something
+        * Cancel any delayed maybeFetch() call and callback the context so
+        * they can cancel any async fetching if they use AJAX or something.
         */
        cancel: function ( context ) {
                if ( context.data.timerID !== null ) {
@@ -93,12 +93,12 @@ $.suggestions = {
                        }
                }
 
-               // Cancel previous call
-               if ( context.data.timerID !== null ) {
-                       clearTimeout( context.data.timerID );
-               }
+               // Cancels any delayed maybeFetch call, and invokes context.config.cancel.
+               $.suggestions.cancel( context );
+
                if ( delayed ) {
-                       // Start a new asynchronous call
+                       // To avoid many started/aborted requests while typing, we're gonna take a short
+                       // break before trying to fetch data.
                        context.data.timerID = setTimeout( maybeFetch, context.config.delay );
                } else {
                        maybeFetch();