起因
我的项目须要做一个上传性能,每次上传20个视频,不解决间接传的话会有一个阻塞问题。
因为一个网页最多同个域名只能有6个tcp连贯。不管制并发同时传6个,用户后续的所有调其余接口的操作都会被挂起来。网络不好的状况下更是劫难,所以须要管制并发,一次最多只传3个。
正好又有这种类型的面试题,写个demo讲下原理。
后端代码
后端须要后整根本的返回,随机提早,随机谬误,能跨域
const http = require('http')
http.createServer((req,res)=>{
const delay = parseInt(Math.random()*5000)
console.log(delay);
setTimeout(()=>{
const returnerror = Math.random()>0.8
// if(returnerror){
// res.writeHead(500,{
// // 'Content-Type': 'text/plain',
// 'Access-Control-Allow-Origin':'*',
// 'Access-Control-Allow-Headers':'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild',
// 'Access-Control-Allow-Methods':'GET',
// }).end('error,from '+req.url+' after '+delay+'ms')
// }else{
res.writeHead(200,{
// 'Content-Type': 'text/plain',
'Access-Control-Allow-Origin':'*',
'Access-Control-Allow-Headers':'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild',
'Access-Control-Allow-Methods':'GET',
}).end('OK,from '+req.url+' after '+delay+'ms')
// }
},delay)
}).listen(3000,()=>{
console.log('服务启动在3000!');
})
前端代码
html次要为了动画的一个展现,就不细说了。
js分为两局部,一部分管制dom渲染,这个也不细说了,第二局部就是并发控制器
input数组外面是申请地址
根底版
并发管制次要是两个函数和一个promise队列
。
- 一个负责一直的
递归
往队列外面加promise。 - 另外一个负责生产promise,解决异步申请逻辑
function handleFetchQueue(input, max) {
const requestsQueue = []; // 申请队列
addReactive(requestsQueue) //对requestsQueue增加响应式
let i = 0;
const req = (i)=>{ //产生一个promise申请 胜利则删除队里中promise 再增加一个申请
return fetch(input[i]).then(res=>res.text()).then(res=>{
addEl(res) //后果渲染页面列表
const index = requestsQueue.findIndex(item=>item===req)
requestsQueue.splice(index,1)
checkAddReq()
})
}
const checkAddReq = ()=>{
if(i>=input.length) return // 申请数不能越界
if(requestsQueue.length+1 <= max) { // 并发不能越界
setTimeout(()=>{ //加提早为了进步动画成果,理论不须要
requestsQueue.push(req(i++))
checkAddReq()
},50)
}
}
checkAddReq();
}
handleFetchQueue(input,3)
解决异样
须要思考的问题是异样了怎么办。
异样对于并发管制也就是计数原理应该没有区别,只是须要额定再promise生成这里增加下业务逻辑即可。
咱们把后端代码随机谬误的正文关上
而后前端外围逻辑改一下
const req = (i)=>{
return fetch(input[i]).then(async(res)=>{
if(res.status===500){ //这里异步改一下,得让走catch
const text = await res.text()
throw new Error(text);
}else{
return res.text()
}
}).then(res=>addEl(res),error=>addEl(error,true))
.finally(()=>{ //无论成功失败并发逻辑一样,只是then中业务逻辑不同
const index = requestsQueue.findIndex(item=>item===req)
requestsQueue.splice(index,1)
checkAddReq()
})
}
总结
残缺地址 https://github.com/fyy92/code…
- index.html 不思考异步
- index1.html 思考异样
- serve.js 后端代码
总结一下
- 并发管制要害在两个函数,一个管制生成业务Promise,一个迭代管制并发队列增加业务Promise。
- 对于异样,须要保障并发逻辑一样,不同的是业务逻辑的解决。
发表回复