使用Promise解决并发问题,处理reject情况

前言

当你搜到这篇文章的时候,说明你在面试中遇到过这种问题,但是好多文章用例不清晰,只处理了并发的事情,没有处理后续回掉逻辑,本文结合一道面试题展开介绍如何解决并发问题。

需求

  • 多个请求,要求并发处理
  • 处理resolve,reject情况
  • 用promise去实现

场景

先构建场景。封装一个fetch函数用来调用接口,接口有一半的可能返回成功,一半失败。

const fetch = (url) => {
    return () => new Promise((resolve, reject) => {
        setTimeout(() => {
            Math.random() > 0.5 ? resolve(url) : reject(url)
        }, 2000);
    })
}

然后构建多个请求:

const request = SuperRequest(3)
for (let i = 1; i <= 5; i++) {
    request(`/test${i}`)
        .then(res => {
            console.log(res);
        })
        .catch(err => {
            console.log('err:', err);
        })
}

SuperRequest传入的是并发值,需要去完成SuperRequest函数。

思路

思路肯定是很清晰的,使用闭包去实现,需要有值记录running中的请求使其小于并发值。难点可能是当并发中的请求执行完毕之后,怎么去增加一个新的请求,并正确触发其成功或失败的回掉。

实现方案

代码中需要注意两件事情:

  1. tasks是全部任务,在push的时候需要把对应的resolve,reject带入,这样当这个任务执行的时候可以去触发resolve,reject的回掉。
  2. 使用then,catch去触发resolve,reject,使用finally意味着当前请求执行完毕,需要去添加一个新请求
function SuperRequest(limit) {
    let tasks = []
    let runingCount = 0
    const _run = () => {
        while (runingCount < limit && tasks.length > 0) {
            const { task, resolve, reject } = tasks.shift()
            runingCount++
            Promise.resolve(task())
                .then(resolve)
                .catch(reject)
                .finally(() => {
                    runingCount--
                    _run()
                })
        }
    }
    return (url) => {
        return new Promise((resolve, reject) => {
            const task = fetch(url)
            tasks.push({ task, resolve, reject })
            _run()
        })
    }
}
function SuperRequest(limit) {
    let tasks = []
    let runingCount = 0
    const _run = () => {
        while (runingCount < limit && tasks.length > 0) {
            const { task, resolve, reject } = tasks.shift()
            runingCount++
            Promise.resolve(task())
                .then(resolve)
                .catch(reject)
                .finally(() => {
                    runingCount--
                    _run()
                })
        }
    }
    return (url) => {
        return new Promise((resolve, reject) => {
            const task = fetch(url)
            tasks.push({ task, resolve, reject })
            _run()
        })
    }
}

文章转自:https://juejin.cn/post/7373808202867130420

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值