js經(jīng)常會遇到異步的執(zhí)行,簡單的異步執(zhí)行可以使用回調(diào)峰伙,多個(gè)異步回調(diào)執(zhí)行可以使用await/async解決疗疟。遇到多個(gè)不定的異步需要同步一個(gè)一個(gè)執(zhí)行的時(shí)候,無法直接執(zhí)行瞳氓,例如多個(gè)網(wǎng)絡(luò)請求策彤,需要一個(gè)一個(gè)去執(zhí)行,就會遇到任務(wù)隊(duì)列串行執(zhí)行的問題匣摘。
在遇到多個(gè)需要異步執(zhí)行的promise時(shí)店诗,可以直接使用promise提供了all方法同時(shí)執(zhí)行多個(gè)promise,但是并未能解決異步的任務(wù)是不斷產(chǎn)生的情況音榜。在異步任務(wù)不斷產(chǎn)生而且需要順序的執(zhí)行完一個(gè)才能執(zhí)行下一個(gè)的情況下庞瘸。使用定時(shí)器和隊(duì)列來解決,新任務(wù)加入隊(duì)列赠叼,隊(duì)列不斷拿出任務(wù)執(zhí)行擦囊,就可以做到串行化執(zhí)行了。
export interface PromiseQueueOptions {
interval?: number;
}
export default class PromiseQueue {
private interval?: any;
// 選項(xiàng)
private options: PromiseQueueOptions;
// 鎖定
private lock = false;
// 隊(duì)列
private queue: (() => Promise<any>)[] = [];
static instance(options: PromiseQueueOptions = {}): PromiseQueue {
if (options.interval == undefined) options.interval = 200;
return new PromiseQueue(options);
}
constructor(options: PromiseQueueOptions) {
this.options = options;
this.interval = setInterval(async () => {
// 沒有任務(wù)或者任務(wù)執(zhí)行中情況不執(zhí)行
if (this.queue.length > 0 && !this.lock) {
console.log('execute queue');
// 鎖定
this.lock = true;
// 取出函數(shù)
const f = this.queue.shift();
// 解鎖
await f!();
this.lock = false;
}
}, options.interval);
}
// 加入隊(duì)列
push(f: () => Promise<any>) {
this.queue.push(f);
}
// 釋放隊(duì)列
destory() {
clearInterval(this.interval);
}
}