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

一、背景

  在写项目的时候有时候在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 为异步也好,同步也好都不影响。
  • 15
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

lytao123

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

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

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

打赏作者

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

抵扣说明:

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

余额充值