JavaScript AJAX节点作用域问题:编写的异步代码执行异常求助
Hey there! Let's walk through the scope-related issues and fixes in your AJAX code—this is a common pitfall for folks working with callbacks in loops, so you're asking the right questions.
1. Implicit Global xhttp Variable
Right now, you're declaring xhttp without var, let, or const inside your loop. That makes it a global variable, which means every iteration of the loop overwrites the same xhttp reference. When your AJAX callbacks fire later (since they're asynchronous), all of them will point to the last xhttp instance you created. This can cause weird behavior like callbacks using the wrong response data or status checks failing.
Quick Fix: Add let before xhttp to give it block-level scope within each loop iteration:
let xhttp = new XMLHttpRequest();
2. Callback Scope for i (You’re Already Doing This Right!)
Great call using let i instead of var i in your loop. In ES6+, let creates a new binding for i in each loop iteration. That means when your asynchronous callback runs, it’ll reference the correct i value for that specific loop pass—no classic closure trap here. If you were using var, all callbacks would share the same i variable, which would end up being equal to abils.length by the time callbacks fire. Just make sure your target environment supports ES6 (all modern browsers do, but if you need to support older ones, you might need Babel to transpile).
3. Broken Success Condition Logic
Your onreadystatechange callback has two issues with the success check:
- You’re using
||instead of&&:readyState == 4means the request is complete, but you only want to act if the response is successful (status == 200). Using||would run the code even if the request completed with an error status (like 404 or 500). - You’re referencing
statusinstead ofxhttp.status: Without thexhttp.prefix, you’re looking for a globalstatusvariable, which is almost certainlyundefinedhere.
Fixed Condition:
if (xhttp.readyState === 4 && xhttp.status === 200) { abils[i].parentNode.parentNode.innerHTML = this.responseText; }
4. Trailing & in Your URL
When abils[i].value isn’t empty, you’re appending & to the end of your URL. This can cause problems for backend parsers, which might interpret it as an empty parameter. A cleaner way to build your URL is to use template literals and handle the parameter properly:
let url = 'my url'; if (abils[i].value !== '') { // Use encodeURIComponent to escape special characters in the value url += `?id_abil=${encodeURIComponent(abils[i].value)}`; }
If you ever need to add more parameters later, you can collect them in an array and join with & to avoid trailing characters:
const params = []; if (abils[i].value !== '') params.push(`id_abil=${encodeURIComponent(abils[i].value)}`); if (someOtherValue) params.push(`other_param=${encodeURIComponent(someOtherValue)}`); const url = 'my url' + (params.length ? `?${params.join('&')}` : '');
Bonus: Modernize with fetch
If you don’t need to support super old browsers, the fetch API is a cleaner alternative to XMLHttpRequest. It uses Promises, which avoid a lot of callback scope headaches and make error handling more straightforward:
const abils = document.getElementsByName('aggiunta_abil'); for (let i = 0; i < abils.length; i++) { const abil = abils[i]; let url = 'my url'; if (abil.value !== '') { url += `?id_abil=${encodeURIComponent(abil.value)}`; } fetch(url) .then(response => { // Check if the response was successful if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`); return response.text(); }) .then(html => { abil.parentNode.parentNode.innerHTML = html; }) .catch(error => { console.error('Fetch failed:', error); }); }
Hope this clears up the scope issues and helps you get your AJAX calls working reliably!
内容的提问来源于stack exchange,提问作者Riccardo Paoletti

