控制并发是 Promise 中比较重要、也比较常见的使用场景之一。 那么在面试中可能会有关于此方面的题目,下面我们来详细讲解一下控制并发的面试题攻略。
什么是并发控制?
并发控制指的是对于某些需要进行并发处理的操作,保证其并发数量的控制。
举个例子,假设我们现在需要爬取若干个网页,但是为了对目标网站造成压力使用单线程轮流爬取的策略并不可取,这时我们就可以用 Promise 来控制每次并发的数量。
Promise 中的限制并发的方法
1. 控制并发的核心方法 promiseLimit()
下面的程序代码中 corePromise() 是一个返回 Promise 的函数,执行上限设置为 limit,即 limit 个请求并发,拿到结果后将结果存到 results 中,并在所有请求完毕后一起返回。
const promiseLimit = async (arr, corePromise, limit) => {
let results = [],
index = 0;
const doing = (task) => {
return new Promise(resolve => {
const i = index++;
Promise.resolve().then(async () => {
results[i] = await corePromise(task);
}).finally(() => {
resolve();
});
})
};
let promises = arr.map(task => doing(task));
await Promise.all(promises);
return results;
};
promises 对单个任务的并发限制(限制单个任务只有在结果返回后才开始下一个任务)使用自己暴露出的接口(例如:doSomethingAsync(),也可以是 Promise 的实例方法)的方式实现,即通过 Promise.resolve().then() 来控制每次并发的数量。返回值 results 是所有任务执行完毕返回的数据集合。
2. 示例
下面使用一个获取网页的异步函数getPage() 来演示 promiseLimit() 的应用。
若我们有一个数组 urls,需要一次性并发请求 3 个网页,且请求的代码逻辑都一样,则可以使用如下代码来控制并发数量:
const task = async url => {
const html = await getPage(url);
return html;
};
const urls = ['url1', 'url2', 'url3', 'url4', 'url5', 'url6'];
const res = await promiseLimit(urls, task, 3);
上述代码中,遍历 urls 数组,每个 url 都会发送请求,但每次的并发数量将不会超出 3 个。
Promise 中的完整示例
下面给出一个完整的示例,该例子演示如何获取 30 条《红楼梦》的不同章节,限制并发数量为 5:
1. 获取章节名数组
async function fetchChapterTitles() {
const res = await got.get('https://www.shicimingju.com/book/hongloumeng.html');
// 利用正则匹配出所有章节链接
const chapterLinks = res.body.match(/(?<=<a href=")\/chapter\/[^"]+(?=">)/g);
const chapterTitles = await promiseLimit(
chapterLinks.slice(0, 30), // 我们只需要前 30 个章节
async (link) => {
const pinyin = link.split('/').slice(-1)[0];
const url = `https://www.shicimingju.com/chapter/${pinyin}.html`;
const res = await got.get(url);
const title = res.body.match(/(?<=<h1>)[^<]+/g);
return `[第${title[0]}回]`;
},
5 // 最多同时 5 个并发请求
);
return chapterTitles;
}
2. 运行程序
将上述代码保存到一个 .js 文件中,并运行如下程序:
const titles = await fetchChapterTitles();
console.log(titles);
执行结果将会输出《红楼梦》前 30 章的章节名称。
以上就是 Promise 面试题详解之控制并发的攻略。对于面试官提及的相关问题,可以根据上述方法进行回答,同时要注意在实现中保持代码的规范和正确性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Promise面试题详解之控制并发 - Python技术站