串行按序发送100个Ajax请求

串行按序发送100个Ajax请求

在面试中不止一次被问到如何串行的发送n个网络请求,回答的时候总是迷迷糊糊。因为平常都是在看别人的文章,这方面没有实际动手实践过。但是看完别人的文章,印象总是不太深刻。这次希望自己一步一步可以通过多种方法来实现串行连续发送100个网络请求。

1. 编写一个node服务用来接收ajax请求

为了能够直观的看到效果,这里使用了nodejs的koa框架来写了一个最简单的服务端,来接收客户端的 ajax post 请求。

server.js

const Koa = require('koa')
const app = new Koa()
const Router = require('koa-router')
const router = new Router()
const bodyParser = require('koa-bodyparser')
const cors = require('koa-cors')

// 由于服务器与客户端端口不同,需要 cors 中间件处理跨域请求
app.use(cors())
// 使用 bodyParser 中间件来解析 post 请求的请求体
app.use(bodyParser())
// 使用 koa-router 路由中间件来处理对应 URL 的请求事件  
app.use(router.routes())






router.post('/ajaxTest',async ctx => {    
    let order=ctx.request.body.order
    // 打印出客户端传递的当前第n个请求的序号
    console.log(order)
    // 返回给客户端的数据
    ctx.body = {success:true,data:'成功'}
});

app.listen(3000)

server.js 是koa服务端,由于客户端端口号和服务端不同(客户端80,服务端3000),所以需要做跨域处理,这里为了方便直接使用了 cors 插件,该服务器只接收一种请求,就是请求地址为http://127.0.0.1:3000/ajaxTest,且请求类型为 post 的 ajax 请求。

接下来是客户端

client.html

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>按序串行发送100个ajax</title>
</head>
<body>
	<script>
		function myajax(url,data,method,success,async = true){
		    // 1. 创建对象
		    var xhr
		    if (window.ActiveXObject) {  
		    	xhr =  new ActiveXObject("Microsoft.XMLHTTP");  
		  	} else if (window.XMLHttpRequest) {  
		    	xhr = new XMLHttpRequest();  
		  	}
		    if(method == 'get'){
		        // 处理get请求,data 包含在 url 地址中
		        if(data){
		            url += '?'
		            url += data
		        }
		        // 2.设置方法和url
		        xhr.open(method,url,async)
		        // 3.发送请求
		    	xhr.send()
		    } else {
		        // 处理post请求
		        xhr.open(method,url,async)
		        // 2. 设置请求报文 指定编码格式
		        xhr.setRequestHeader("Content-type","application/json");
		        // 3.发送请求
		        if(data){
		    		// data 在 send 中发送
		            xhr.send(data)
		        }else{
		            xhr.send()
		        }
		    }
		    
		    // 4.注册事件
		    xhr.onreadystatechange = function(){
		        if(xhr.readyState == 4 && xhr.status == 200){
		            // 5.使用回调函数
		            success(xhr.responseText)
		        }
		    } 
		}
		myajax('http://127.0.0.1:3000/ajaxTest',JSON.stringify({order:1}),'post',(res)=>{
			var data = JSON.parse(res).data
			console.log(data)
		})

	</script>
</body>
</html>

这里的 myajax 是封装的原生的 ajax 函数,没有用第三方插件的 Ajax 方法也是为了方便对传递的参数的理解。

这里先不急着发送100个ajax请求,先发送一个请求看看服务端能不能收到数据。

终端下运行命令 node server 启动服务器

直接双击打开 client.html 客户端,页面加载完便会发送一个ajax请求 

服务器收到请求后在终端打印出一个1,说明请求发送成功。

1.1 尝试使用for循环发送请求

首先通过默认的 myajax 函数,先尝试向同一个地址发送 5 个请求。

for(let i = 1; i <= 5; i++){
	myajax('http://127.0.0.1:3000/ajaxTest',JSON.stringify({order:i}),'post',(res)=>{
		var data = JSON.parse(res).data
		console.log(data)
	})
}

由于请求发送的数据比较简单,又是访问的是同一个地址,大部分情况下序号的打印都是有序的,在大量数据的测试下,还是会出现发送的请求处理的顺序发生错位的情况,例如上图中的一次请求打印的结果是 1,2,3,5,4  正常按序的打印的结果应该是1,2,3,4,5,这里异步请求处理的顺序就发生了错位。 

然后我把服务端的输出做了下微调

router.post('/ajaxTest',async (ctx,next) => {    
    let order=ctx.request.body.order
    console.log('当前执行的是:'+order)
    ctx.body = {success:true,data:'成功'}
    next()
});

同时把客户端发送的ajax请求增加到100个

for(let i = 1; i <= 100; i++){
	myajax('http://127.0.0.1:3000/ajaxTest',JSON.stringify({order:i}),'post',(res)=>{
		var data = JSON.parse(res).data
		console.log(data)
	})
}

 

因为ajax请求是异步的,这时候前10个ajax请求处理的顺序错位就比较厉害了,就无法达到按序处理的效果。但是10个以后的请求顺序基本没有错乱。

* 有时候应用的场景要求是对100个不同的url地址发起请求,这里为了方便,只对一个 url 地址发起请求,实际上也是也一样的,只不过写100个 url 响应很麻烦而已。

1.2 第一种方案,设置 ajax 请求为同步而不是异步

ajax请求默认是异步的,由于是异步的就无法保证ajax请求按序执行,这时候只要把 ajax 的 async 属性设置成 false,即可同步等待逐个发送请求。

这里试着把 ajax 的 async 属性设置为 false 变成同步处理,默认为 true 为异步。先发10个请求试试。

for(let i = 1; i <= 10; i++){
	myajax('http://127.0.0.1:3000/ajaxTest',JSON.stringify({order:i}),'post',(res)=>{
		var data = JSON.parse(res).data
		console.log(data)
	}, false)
}

反正至少在我测试的几十次内都没有发生错位。理论上也不会发生错位的情况,毕竟浏览器要等待ajax请求一个一个执行。

这种方法在少量 ajax 请求的时候可以,但是 ajax 请求一旦增多到 100,甚至 1000 个的时候,处理的时间增长,由于设置了同步,浏览器会等待 ajax 请求一个一个执行,页面会发生假死的情况,不能操作页面的任何内容,给用户带来的体验很不好。

 

1.3 第二种方案,尝试使用递归回调的方式发送请求

服务端代码不变,客户端用递归的方式来发送请求。其实就是在上一个ajax成功的回调里面继续调用一下ajax,然后使用一个公共的计数器来记录当前所在的序号,当序号到达要请求的数组的末尾的时候,结束递归。

client.html中的代码如下(封装的myajax部分不变)

var data = []
for(let i = 1; i <= 100; i++){
	data.push(i)
}
var currentIndex = 0

function sendRequest(){
	if(currentIndex == data.length){
		// 递归结束的条件
		return;
	}
	var order = data[currentIndex]

	myajax('http://127.0.0.1:3000/ajaxTest',JSON.stringify({order:order}),'post',(res)=>{
		res = JSON.parse(res).data
		if(res == "成功"){
			currentIndex++
			sendRequest()
		} 
	})
}
sendRequest()

这里也可以把 data 数组中的数据换成 url 地址,把固定的 url 地址部分换成变量,就变成了按序请求 100 个 url 地址。 

由于是前一个ajax发送成功后在回调里面再继续执行下一个请求,所以这里一定是有序的。

1.4 第三种方案 async/await 方法

要使用 async 和 await 方法就要重新封装 ajax 方法,因为 await 后面是一个 Promise 对象,所以需要把 ajax 方法放到一个Promise对象中去返回。

function ajax(url, data){
	return new Promise((resolve,reject)=>{
		myajax(url,JSON.stringify({order:data}),'post',(res)=>{
			resolve(res)
		})

	}).then((res)=>{
		var data = JSON.parse(res).data
		console.log(data)
	})
}



async function sendRequest() {
	for(let i = 1; i <= 100; i++){
		await ajax('http://127.0.0.1:3000/ajaxTest',i)
	}
}

sendRequest()

async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等异步操作完成,再接着执行函数体内后面的语句。这也就保证了 ajax 请求能够串行执行。 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值