JS设置全局变量在ajax中赋值不上原因分析及问题解决

本文探讨了在Ajax异步请求中给全局变量赋值失败的原因,并提供了两种解决方案:一是将Ajax请求改为同步请求;二是将请求结果及其业务处理逻辑整合在一起。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、背景

  在写项目的时候有时候在Ajax中请求了后端返回的数据,不想在success中处理或需要将结果带出Ajax(可能是业务需求),这时就需要处理了。一般解决方法是想办法将 Ajax 请求返回的结果同业务处理逻辑都放到 Ajax 中或者定义一个全局变量存数据,而定义一个全局变量,然后再在ajax中赋值可能就会出现这个问题,为什么我在这说可能出现这个问题呢?这个原因且听我慢慢道来。

二、Ajax中给全局变量赋值不上的原因

  在Ajax中给全局变量赋值不上主要是因为Ajax默认是异步请求。为更清楚直观地知道这个原因,在这里我写了代码测试。
  首先是我新建了一个叫Test2的项目,然后在后端写了这样的代码,大家都知道通过 Ajax 向后端请求这个 Servlet 会返回数据 Text 数据“后台返回的数据”。

package com.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class TestServlet
 */
@WebServlet("/testServlet")
public class TestServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		response.getWriter().write("后台返回的数据");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

}

  其次我写的 JS 代码如下,然后在控制台时刻打印出全局变量 _STR 的值,我给打印的内容标上了序号 12345 ,我们期望的打印顺序也是 12345 的依次打印在控制台。
注意:我这里用的是 Ajax 异步请求。

var _STR = "默认值";
function test() {
	console.log("1.在ajax赋值前ajax外面  _STR 的值:" + _STR);
	var url = "<%=request.getContextPath() %>/testServlet";
	$.ajax({
		url: url,
		type:'post',
		async: true,
		dataType: 'text',
		data: {
		},
		success: function(data) {
			console.log("2.在ajax赋值前ajax里面  _STR 值:" + _STR);
			console.log("3.data = " + data);
			_STR = data;   //给全局变量赋值
			console.log("4.在ajax中赋值后ajax里面  _STR 的值:" + _STR);
		}
	});
	console.log("5.在ajax赋值后ajax外面  _STR 的值:" + _STR);
}

  然后,我在前端 JSP 写了下面这段的代码,为了能通过点击按钮能触发 JS 写的函数 test 。

<input type="button" onclick="test()" value="js全局变量ajax赋值">

  现在我们就开始测试(Ajax 是异步请求),下图是测试结果:
控制台打印出来的顺序是 15234
  控制台打印出来的顺序是 15234,和我们预期的结果 12345 不一样,产生这样的原因是因为什么我们先不说,暂留这个问题;然后我们在来看其中的 全局变量 _STR 的值 第1步打印的值是 “默认值”,在第5步打印的值和第一步一样,第2步和预期(_STR 的值是”默认值“)的一样,第3步是打印返回的值,作用是确定返回的值是后端返回的,第4步 _STR 的值和预期(_STR 的值是后端返回的值)一样。这里主要的问题是第5步比第234步执行的要快,所以在第234步没执行完第5步就拿到了没有赋值前的值,然后一直拿着这个原值执行下去,这就是为什么“赋值不上”。
  紧接着我们将 JS 改动一部分:将第5步不直接打印,改为在 Ajax 请求完并赋值给全局变量后 打印 _STR 的值,我就给了它4秒后打印,这样4秒的时间 Ajax 请求应该能请求完并赋值给全局变量了吧。

var _STR = "默认值";
function test() {
	console.log("1.在ajax赋值前ajax外面  _STR 的值:" + _STR);
	var url = "<%=request.getContextPath() %>/testServlet";
	$.ajax({
		url: url,
		type:'post',
		async: true,
		dataType: 'text',
		data: {
		},
		success: function(data) {
			console.log("2.在ajax赋值前ajax里面  _STR 值:" + _STR);
			console.log("3.data = " + data);
			_STR = data;   //给全局变量赋值
			console.log("4.在ajax中赋值后ajax里面  _STR 的值:" + _STR);
		}
	});
	// 将这里改为4秒后打印 _STR 的值
	setTimeout(function () {
		console.log("5.在ajax赋值后ajax外面  _STR 的值:" + _STR);
	}, 4000);
	
}

  果不其然,4秒时间完全够 Ajax 请求完并赋值给全局变量了,见下图,当我们给这个 Ajax 足够的时间去请求后端拿到值,然后赋值给全局变量,再打印出结果。从这里我们可以看出其实是给全局变量附上值了的,只是后面的代码没有拿到赋值后的值。
控制台按12345的顺序打印结果,最先打印的是1234,过了一会打印5
  然后我们将 Ajax 改为同步async: false,接着测试,下图是测试结果
控制台打印出来的顺序是 12345
  控制台打印出来的结果是 12345 ,和我们想要的结果一样。
综上所述,JS 设置全局变量在 Ajax 中赋值不上的原因是 Ajax 为异步请求。

三、解决方法

1. 将 Ajax 异步请求async: true,改为同步请求async: false,在上面已有解决步骤。
2. 将 Ajax 请求的结果和对结果的业务处理都尽量放到一起,这是最推荐的做法,这样 Ajax 为异步也好,同步也好都不影响。
<think>我们正在讨论如何使用jQuery设置全局变量并进行赋值。注意:jQuery本身提供特殊的全局变量处理方式,它遵循JavaScript的变量作用域规则。因此,实际上我们讨论的是在JavaScript中如何定义全局变量,并在jQuery代码(如事件处理、AJAX回调等)中使用。根据引用[1][2][3][4][5]的内容,我们可以总结以下几点:1.全局变量可以在函数外部声明,这样它在整个脚本中都是可访问的。2.在函数内部,如果省略var、let或const关键字而直接赋值给一个变量,那么该变量会被视为全局变量(前提:非严格模式)。3.在jQuery的AJAX回调中,我们经常需要将返回的数据赋值全局变量,但要注意AJAX默认是异步的,因此赋值操作可能在数据返回前执行,导致全局变量为undefined。因此,我们重点讨论:-如何声明全局变量-在jQuery代码中(如事件处理、AJAX回调)给全局变量赋值-注意事项(如作用域、异步问题)步骤:1.声明全局变量:在jQuery代码外部,使用`var`(函数作用域)或省略`var`(推荐,严格模式会报错)或使用`window`对象来定义全局变量。例如:```javascriptvarglobalVar;//全局变量window.globalVar2;//也是全局变量,等价于varglobalVar2;```2.在jQuery代码中赋值:在jQuery的事件处理函数、AJAX回调等内部,可以直接给全局变量赋值。示例1:在事件处理函数中赋值```javascript$(document).ready(function(){//给全局变量赋值globalVar="Hello,World!";});```示例2:在AJAX回调中赋值(注意异步问题)```javascriptvarajaxResult;//全局变量$.ajax({url:"example.com/data",success:function(data){ajaxResult=data;//在回调中赋值}});//注意:这里能立即使用ajaxResult,因为AJAX是异步的,此时可能还没有数据```3.解决AJAX异步问题:由于AJAX默认是异步的,在回调函数外部无法立即获取到赋值后的全局变量解决方法:-将后续操作放在回调函数内部-使用同步AJAX推荐,会阻塞页面)-使用Promise或async/await例如,使用回调函数内部操作:```javascript$.ajax({url:"example.com/data",success:function(data){ajaxResult=data;//在这里调用处理数据的函数processData();}});functionprocessData(){console.log(ajaxResult);//可以正确获取}```4.另一种定义全局变量的方法:使用window对象```javascriptwindow.myGlobal="value";//在任何地方都可以通过window.myGlobal或myGlobal访问```5.注意事项:-避免滥用全局变量,防止命名冲突和难以维护。-在jQuery的`$(document).ready()`函数内部定义的变量,如果使用`var`声明,则在该函数外部无法访问(局部变量)。因此,要定义全局变量,必须在函数外部声明,或者在函数内部使用`var`(但推荐,因为严格模式下会报错,且易出错)。-引用[5]提到,`$(function(){})`在DOM结构创建完成后执行,而`window.onload`在整个页面加载完成后执行。在`$(function(){})`内部定义的变量,如果使用`var`,则作用域仅限于该函数内。示例代码:以下是一个完整的示例,展示在jQuery中如何设置全局变量并在同地方赋值和使用:```html<!DOCTYPEhtml><html><head><title>jQueryGlobalVariableExample</title><scriptsrc="https://code.jquery.com/jquery-3.6.0.min.js"></script><script>//声明全局变量varglobalVar;$(document).ready(function(){//给全局变量赋值globalVar="Initializedinready";//通过按钮点击事件修改全局变量$("#btnSet").click(function(){globalVar=$("#inputText").val();$("#output").text("Globalvariableisnow:"+globalVar);});//使用AJAX获取数据并赋值全局变量$("#btnAjax").click(function(){//模拟AJAX请求$.ajax({url:"https://jsonplaceholder.typicode.com/todos/1",success:function(data){globalVar=data.title;$("#output").text("FromAJAX:"+globalVar);}});});});//可以在另一个函数中使用全局变量functionshowGlobalVar(){alert("CurrentglobalVar:"+globalVar);}</script></head><body><inputtype="text"id="inputText"placeholder="Entervalue"><buttonid="btnSet">SetGlobalVariable</button><buttonid="btnAjax">SetviaAJAX</button><buttononclick="showGlobalVar()">ShowGlobal</button><divid="output"></div></body></html>```在这个示例中:-全局变量`globalVar`在`$(document).ready()`外部声明。-在`$(document).ready()`内部,我们给全局变量赋初始值。-通过按钮点击事件可以修改全局变量的值(直接赋值或通过AJAX回调赋值)。-另一个函数`showGlobalVar`也可以访问和显示这个全局变量。注意:在AJAX回调中赋值时,由于异步特性,在回调外部立即访问`globalVar`可能还是旧值。因此,我们通常在回调内部使用全局变量,或者通过回调触发后续操作(如更新DOM)。相关问题:1.如何在jQuery中避免全局变量污染?[^1][^2]2.jQueryAJAX异步请求中如何确保全局变量赋值后执行后续操作?[^3][^4]3.使用jQuery时,全局变量和局部变量作用域的区别是什么?[^1][^5]4.在多个jQuery事件处理函数中如何安全地共享全局变量?[^1][^5]以上内容结合了引用的知识点,并提供了实际示例。请注意,在引用中多次提到了在AJAX回调中赋值全局变量可能遇到的异步问题,因此在实际应用中需要特别注意。</think>### 如何使用 jQuery 给全局变量赋值 在 jQuery 中设置全局变量本质上遵循 JavaScript 的作用域规则,以下是几种核心方法及注意事项: #### 方法一:在函数外部声明(推荐) ```javascript // 声明全局变量 var globalData; $(document).ready(function() { // 在事件中赋值 $("#btn").click(function() { globalData = $(this).text(); // 给全局变量赋值 console.log(globalData); // 可在任何地方访问 }); }); ``` **特点**: - 通过 `var` 在函数外部声明 - 所有函数和事件处理器都可访问[^1] - 符合标准作用域规则 #### 方法二:使用 `window` 对象 ```javascript $(function() { $("#btn").click(function() { window.appConfig = { // 通过 window 对象定义 theme: "dark", version: "1.0" }; }); }); // 其他地方访问 console.log(window.appConfig.theme); ``` **适用场景**: - 需要在严格模式下声明全局变量 - 需要明确表明变量的全局属性[^2] #### 方法三:AJAX 回调中赋值(需处理异步) ```javascript var apiResponse; // 全局变量 $.ajax({ url: "https://api.example.com/data", success: function(data) { apiResponse = data; // 回调中赋值 processData(); // 必须在此处调用后续处理 } }); // ❌ 错误用法:此处 apiResponse 可能未定义 console.log(apiResponse); // ✅ 正确处理异步数据 function processData() { console.log(apiResponse); // 确保数据已赋值 } ``` **关键点**: - AJAX 默认异步执行,需在回调函数内使用全局变量[^3][^4] - 使用 `async: false` 可同步执行(推荐,会阻塞页面) #### 作用域对比表 | 变量类型 | 声明位置 | 访问范围 | 示例 | |----------------|------------------------|-------------------|-----------------------| | 全局变量 | 所有函数外部 | 整个页面 | `var global;` | | 局部变量 | 函数内部 | 仅限当前函数 | `function(){ var x }` | | `window`属性 | 任意位置 | 全局 | `window.app = {}` | | 未声明直接赋值 | 任意位置(推荐) | 全局(严格模式报错)| `unDeclared = 1` | #### 完整示例 ```html <script> // 全局计数器 var clickCount = 0; $(function() { // 局部变量(仅在此函数内有效) var buttonColor = "blue"; $(".btn").click(function() { // 修改全局变量 clickCount++; // 访问DOM元素 window.lastClicked = $(this).attr('id'); updateUI(); }); function updateUI() { // 访问全局变量 $("#counter").text(clickCount); console.log(window.lastClicked); } }); </script> ``` ### 注意事项 1. **异步问题**:在 AJAX 回调中赋值时,后续操作必须在回调内执行[^3][^4] ```javascript // 正确示例 $.get("/data", function(res) { window.data = res; initPage(); // 在回调内执行后续操作 }); ``` 2. **命名冲突**:使用命名空间避免污染全局空间 ```javascript // 创建命名空间 window.MyApp = {}; MyApp.config = { theme: "dark" }; ``` 3. **执行时机**: - `$(document).ready()` 在 DOM 就绪后执行 - `window.onload` 在所有资源加载后执行[^5] - 全局变量应在这些事件前声明 4. **严格模式**:未声明的变量赋值会报错 ```javascript "use strict"; undeclaredVar = 10; // 抛出 ReferenceError ``` ### 相关问题 1. 如何在 jQuery AJAX 回调中安全地使用全局变量?[^3][^4] 2. 如何避免 jQuery 中的全局变量污染?[^1] 3. `$(document).ready()` 和 `window.onload` 处理全局变量有何区别?[^5] 4. 为什么在 AJAX 成功回调外部访问全局变量会得到 `undefined`?[^4] 5. 如何用 jQuery 实现模块化的全局状态管理?
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lytao123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值