jQuery UI Autocomplete因变量作用域导致response()无法返回动态结果
Hey there, let's tackle this frustrating issue you're facing with jQuery UI Autocomplete. The core problem here is how you're handling asynchronous operations and the timing of the response() call, plus some misplacement of where you define your dynamic source.
Why Your Current Code Isn't Working
When you redefine the source inside the select event and immediately trigger a search, the Autocomplete initiates the search request, but your getAutocompleteResults is asynchronous (it's making an AJAX call, right?). By the time your callback runs and calls response(d), the Autocomplete has already moved on from that specific search context—it doesn't recognize the delayed response() call anymore. That's why static arrays work (they're synchronous) but your dynamic data doesn't.
Step-by-Step Solution
1. Define Your Async Source During Initialization
Instead of redefining source every time the user selects an item, set it up once when you initialize Autocomplete. This way, every search (including the one triggered after selection) will properly handle the asynchronous response.
// Track pending AJAX requests to avoid race conditions let activeXhr; $("#search").autocomplete({ // Set up the async source once source: function(request, response) { // Cancel any pending request before sending a new one if (activeXhr) { activeXhr.abort(); } // Pass the search term to your async function activeXhr = getAutocompleteResults(request.term, function(d) { // Format your data to match Autocomplete's requirements // It needs at least `label` or `value`; add your custom properties too const formattedResults = d.map(item => ({ label: item.title, value: item.title, extract: item.extract, pageId: item.pageId })); // Send the formatted results back to Autocomplete response(formattedResults); // Clear the active request reference activeXhr = null; }); }, select: function(e, ui) { // Update your display element $('#instant-search').text(ui.item.label); // Trigger a new search using the selected item's label $("#search").autocomplete("search", ui.item.label); // Prevent default if you don't want the input to auto-fill with ui.item.value e.preventDefault(); } });
2. Ensure getAutocompleteResults Handles Async Correctly
Make sure your async function accepts the search term and callback, and properly resolves the AJAX request:
function getAutocompleteResults(searchTerm, callback) { return $.ajax({ url: "your-api-endpoint-here", // Replace with your actual URL data: { term: searchTerm }, dataType: "json", success: function(data) { callback(data); }, error: function() { // Fallback to empty array if the request fails callback([]); } }); }
Key Fixes Explained
- Persistent Source Definition: By setting the async source during initialization, every search (including post-selection) uses the same reliable logic, and
response()will always be tied to the current search context. - Race Condition Prevention: Tracking
activeXhrlets us cancel pending requests before sending new ones, so you never get outdated results from a slow previous request. - Data Formatting: Autocomplete requires
label/valueproperties to render items—mapping your customtitle,extract, andpageIdinto this structure ensures the results display correctly while preserving your custom data.
内容的提问来源于stack exchange,提问作者Lukas Naujokaitis

