实现并发请求的失败自动重试及重试次数限制

转载自一文教你如何实现并发请求的失败自动重试及重试次数限制_javescript重试代码-CSDN博客

let second2 = 0		
let second3 = 0		
function request1() {
  return new Promise((resolve) => {
    setTimeout(() => {
			console.log("请求完毕11")
      resolve(111)
    }, 1000);
  })
}
function request2() {
  return new Promise((resolve, reject) => {
		if(second2 < 2) {
			setTimeout(() => {
			console.log("请求完毕22")
      reject(222)
			second2++
    }, 2000);
		} else {
      setTimeout(() => {
				console.log("请求完毕22")
      resolve(222)
    }, 2000);
		}  
  })
}
function request3() {
  return new Promise((resolve, reject) => {
		if(second3 < 1) {
			setTimeout(() => {
				console.log("请求完毕33")
      reject(333)
			second3++
    }, 3000)
		} else {
     setTimeout(() => {
			console.log("请求完毕33")
      resolve(333)
    }, 3000);
		}
    
  })
}
// 实现一个RequestParallelWithRetry类
class RequestParallelWithRetry {
  requestList
  retryCount
  map = {}
  result = []
// 将传入的请求方法进行标记并保存它们的关系,便于后续请求失败时可以利用这个标记来再次调用这个方法
  constructor(requestList = [], retryCount = 3) {
    this.requestList = requestList
    this.retryCount = retryCount
    // 需要给每个方法添加标记
    this.requestList.forEach((item, index) => {
      item._index = index
      this.map[ index ] = item
    })
  }
	// 实现RequestParallelWithRetry类的send方法,它用来并发发送请求,并且要求能够得知每个请求的执行结果
	send() {
  return new Promise((resolve) => {
    // 1. 将所有的网络请求进行包装,使得其返回结果中携带有_index
    // 2. 发送所有的网络请求
    let queue = []
    this.requestList.forEach(request => {
      // 3. 记录每个请求的重试次数
      request._retryCount = 0
      queue.push(this._wrapRequest(request))
    })

		// 我们在send方法内部递归调用sendAllSettled方法,sendAllSettled方法做的事情很简单:
		// 将queue队列中的请求发送出去
		// 将失败的请求重新添加到队列中,再次发送
    const sendAllSettled = () => {
			// 因为我们这里请求的返回结果都是一个promise对象,因此我们可以利用Promise.allSettled方法来获取所有promise的最终结果:
      Promise.allSettled(queue).then((value) => {
        // 3. 清除发送队列
        queue = []
        console.log('所有请求都完成了', value);
        // 4. 检查是否存在失败的请求
        value.forEach(result => {
          if (result.status === "fulfilled") {
            const { value, index } = result.value
            this.result[ index ] = { value, status: 'fulfilled' }
          }
          else if (result.status === "rejected") {
            const { reason, index } = result.reason
            const request = this.map[ index ]
            if (request._retryCount < this.retryCount) {
              queue.push(this._wrapRequest(request))
              request._retryCount++
            } else {
              this.result[ index ] = { reason, status: 'rejected' }
            }
          }
        })
        //  5. 检查队列中是否还需要发送请求
        if (queue.length) {
          sendAllSettled()
        } else {
          resolve(this.result)
        }
      })
    }

    sendAllSettled()

  })
}
// 包装请求的执行结果
// 我们已经知道了我们重复执行那些失败的请求直到成功,但是还存在一个问题:现在我们只能知道失败请求的结果,但是我们无法根据这个结果来找到原先执行请求的方法。因此,我们需要对传入的请求进行一层包装,使得执行的返回结果中包含一个标记,我们能根据这个标记找到这个请求方法:
_wrapRequest(request) {
  return new Promise((resolve, reject) => {
    request().then((value) => {
      resolve({
        value,
        index: request._index
      })
    }).catch(reason => {
      reject({
        reason,
        index: request._index
      })
    })
  })
}
}
new RequestParallelWithRetry([ request1, request2, request3 ]).send().then((value) => {
  console.log(value);
})

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值