欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

通过队列把同一个接口多次并行调用改为串行调用

程序员文章站 2022-03-09 21:50:14
...

1、需求描述

小程序中实现答题功能,页面中只显示一道题(都是单选),用户选择答案以后提交用户该题的答案,并切换到一下题。

2、问题

后台接口控制同一用户,同一个接口,在未响应之前不可再次调用。所以如果用户答题特别快(乱点)会造成同一接口并行调用。请求会直接被拦截,导致用户答案没有保存成功。

3、解决方案

定义页面全局变量promiseQueue:[],用来将来保存需要执行的回调。定义hasResponse来维护当前是否还有未响应的接口。

data:{
	promiseQueue: [],
	hasResponse: true
}

具体提交试题方法:

submitQuestionRecord: function (id, itemId,cb) {
    let that = this;
    //promise队列,后台接口限制同一接口同一用户在接口未响应时不可再调用。该参数用来维护promise队列。如果有正在提交试题答案记录的promise,则加入到该队列。   对应请求完成后会检查该队列,如果队列有值会取出执行。
    let promiseQueue = that.data.promiseQueue;
    let hasResponse = that.data.hasResponse;
    //如果没有未响应的或者需要执行队列中的promise则调用promise
    //如果有未执行完的promise则加入队列,如果没有未执行完的提交试题答案请求或是再循环执行队列中的promise则直接发送promise请求。
    //该处必须使用hasResponse不能通过promiseQueue.length = 0 判断。因promiseQueue.length = 0时最后的请求有可能还没有相应。必须加入到promise队列中。
    if (hasResponse || arguments.length == 4){ 
      that.setData({
        hasResponse: false
      })
      let requestObj = {
        url: `/assessment/submitQuestionRecord`,
        method: 'post',
        dataobj: {
          id: id,
          itemId: itemId
        }
      };
      app.promiseRequest(requestObj).then((res) => {
        let promiseQueue = that.data.promiseQueue
        let promiseQueueItem = promiseQueue.shift();
        that.setData({
          promiseQueue: promiseQueue
        })
        if (promiseQueueItem) { //如果promise队列中还有待发送的promise
          that.submitQuestionRecord(promiseQueueItem.id, promiseQueueItem.itemId,promiseQueueItem.cb,true)
        }else{
          that.setData({
            hasResponse: true
          })
        }
        cb && cb();
      }).catch((errMsg) => {
        console.log(errMsg);//错误提示信息
      });
    } else { //吧promise加到队列,等待执行
      let promiseQueue = that.data.promiseQueue;
      promiseQueue.push({
        id: id,
        itemId: itemId,
        cb: cb
      })
      that.setData({
        promiseQueue: promiseQueue
      })
    }
}

代码封装的不好,希望大神能提供更优雅的代码。