关于javascript:5分钟搞定Promise控制并发

38次阅读

共计 2325 个字符,预计需要花费 6 分钟才能阅读完成。

起因

我的项目须要做一个上传性能,每次上传 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。
  • 对于异样,须要保障并发逻辑一样,不同的是业务逻辑的解决。

正文完
 0