xunfeiAI/node_modules/miniprogram-queue/es/index.js

172 lines
5.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/// <reference lib="es6"/>
/**
* 微信小程序操作队列封装管理
* @example var rq = new WxQueue(wx.requst);
* @template TParam 微信操作参数类型
* @template TTask 微信操返回task类型
*/
export class WxQueue {
/**
* 创建Wx操作队列
* @param wxFunc Wx操作函数
* @param maxLength 最大队列长度默认10
*/
constructor(wxFunc, maxLength = 10) {
/**
* 任务ID计数器
*/
this.taskid = 0;
/**
* 待完成队列
*/
this.todo = [];
/**
* 保持正在运行的任务
*/
this.taskMap = new Map();
this.operator = wxFunc;
this.MAX = maxLength || 10;
}
/**
* 向队列中添加操作
* @param param 微信操作
*/
push(param) {
const id = ++this.taskid;
if (this.taskMap.size < this.MAX) {
// task队列未满
return this._process(id, param);
}
else if (param.jump) {
// 插队
this.todo.unshift([id, param]);
}
else {
this.todo.push([id, param]);
}
return {
abort: () => { this._abort(id); },
onProgressUpdate: (callback) => { this._onProgress(id, callback); },
onHeadersReceived: (callback) => { this._onHeaders(id, callback); }
};
}
/**
* check and do next task
*/
_next() {
if (this.todo.length > 0 && this.taskMap.size < this.MAX) {
const [taskid, taskOptions] = this.todo.shift();
this._process(taskid, taskOptions);
}
}
/**
* process a task
* @param id task ID
* @param options task param
*/
_process(id, options) {
const oldComplete = options.complete;
let timeoutFailHandle;
let taskTimeoutCancelled = false;
let task;
options.complete = (res) => {
if (timeoutFailHandle) {
// 清理计时器
clearTimeout(timeoutFailHandle);
}
if (options.timestamp && this.taskMap.has(id)) {
res.time = this.taskMap.get(id)[1] || {};
res.time.response = Date.now();
}
this.taskMap.delete(id);
// 原始结束回调
if (oldComplete) {
if (taskTimeoutCancelled) {
res.errMsg = `${(res.errMsg || '').split(':', 1)[0]}: timeout`;
res.timeout = true;
}
oldComplete.call(options, res);
}
this._next();
};
if (options.timeout > 0) {
// 自定义timeout 拦截fail 注入timeout
const oldFail = options.fail;
if (oldFail) {
options.fail = (res) => {
if (taskTimeoutCancelled) {
res.errMsg = `${(res.errMsg || '').split(':', 1)[0]}: timeout`;
res.timeout = true;
}
if (oldFail) {
oldFail.call(options, res);
}
};
}
// 计时器 自定义超时
timeoutFailHandle = setTimeout(() => {
timeoutFailHandle = undefined;
taskTimeoutCancelled = true;
task.abort();
}, options.timeout);
}
task = this.operator(options);
// task progress polyfill
if (options.onProgressUpdate && task.onProgressUpdate) {
task.onProgressUpdate(options.onProgressUpdate);
}
// task onHeadersReceived
if (options.onHeadersReceived) {
task.onHeadersReceived(options.onHeadersReceived);
}
this.taskMap.set(id, [
task,
options.timestamp ? { send: Date.now() } : undefined
]);
return task;
}
/**
* stop and remove a task
* @param taskid - the id of task to abort
*/
_abort(taskid) {
const index = this.todo.findIndex(v => v[0] === taskid);
if (index >= 0) {
const completeCallback = this.todo[index][1].complete;
this.todo.splice(index, 1);
// call back complete.
if (completeCallback) {
completeCallback({ errMsg: 'request:fail abort', cancel: true, source: WxQueue.name });
}
}
else if (this.taskMap.has(taskid)) {
this.taskMap.get(taskid)[0].abort();
this.taskMap.delete(taskid);
}
}
/**
* progress update callback
* https://developers.weixin.qq.com/miniprogram/dev/api/network/download/DownloadTask.onProgressUpdate.html
* @param taskid - task id
* @param callback 回调操作
*/
_onProgress(taskid, callback) {
const result = this.todo.find(v => v[0] === taskid);
if (result) {
result[1].onProgressUpdate = callback;
}
else if (this.taskMap.has(taskid)) {
this.taskMap.get(taskid)[0].onProgressUpdate(callback);
}
}
_onHeaders(taskid, callback) {
const result = this.todo.find(v => v[0] === taskid);
if (result) {
result[1].onHeadersReceived = callback;
}
else if (this.taskMap.has(taskid)) {
this.taskMap.get(taskid)[0].onHeadersReceived(callback);
}
}
}
//# sourceMappingURL=index.js.map