這是一道用來熟練Promise
的題目,給定N個URL,要求使用Promise
在限定併發數爲M(M < N) 的狀況下完成請求。javascript
class PromisePool { constructor(max, fn) { this.max = max; // 最大併發數 this.fn = fn; // 自定義的請求函數 this.pool = []; // 併發池 this.urls = []; // 剩餘的請求地址 } start(urls) { this.urls = urls; // 先循環把併發池塞滿 while (this.pool.length < this.max) { let url = this.urls.shift(); this.setTask(url); } // 利用Promise.race 方法來得到併發池中某任務完成的信號 let race = Promise.race(this.pool); return this.run(race); } run(race) { race .then(res => { // 每當併發池跑完一個任務,就再塞入一個任務 let url = this.urls.shift(); this.setTask(url); return this.run(Promise.race(this.pool)); }); } setTask(url) { if (!url) return; let task = this.fn(url); this.pool.push(task); // 將該任務推入pool併發池中 console.log(`\x1B[43m ${url} 開始,當前併發數:${this.pool.length}`); task.then(res => { // 請求結束後將該Promise任務從併發池中移除 this.pool.splice(this.pool.indexOf(task), 1); console.log(`\x1B[43m ${url} 結束,當前併發數:${this.pool.length}`); }); } } // test const URLS = [ 'bytedance.com', 'tencent.com', 'alibaba.com', 'microsoft.com', 'apple.com', 'hulu.com', 'amazon.com' ]; // 自定義請求函數 var requestFn = url => { return new Promise(resolve => { setTimeout(_ => { resolve(`任務 ${url} 完成`); }, 1000*dur++) }).then(res => { console.log('外部邏輯 ', res); }) } const pool = new PromisePool(3, requestFn); // 併發數爲3 pool.start(URLs);