通过队列把同一个接口多次并行调用改为串行调用
程序员文章站
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
})
}
}