随着前端应用的复杂性不断增加,我们需要越来越多的异步操作来处理数据。但如果我们同时发起多个异步请求,可能会导致请求过多,影响应用性能,甚至崩溃。为了解决这一问题,我们可以使用 Promise 实现多个异步请求的并发控制。
Promise 简介
Promise 是一种 JavaScript 对象,用于处理异步操作。它代表一个值,可能已经可用,也可能尚未可用。Promise 支持链式调用,使得对 async 操作的多次处理和处理结果的多次使用变得更加方便和易于维护。
Promise 提供三种状态:未完成态(pending)、已完成态(fulfilled)和已失败态(rejected)。在任务未完成之前,Promise 处于未完成态。如果任务成功完成,Promise 处于已完成态,并提供一个结果;如果任务未完成且发生了错误,Promise 处于已失败态,并提供一个原因。
Promise 并发控制
在使用 Promise 实现并发控制之前,我们先了解一下 Promise.all()。Promise.all() 接受一个 Promise 数组作为参数,返回一个 Promise,当所有 Promise 都已经 resolve 后,返回一个 resolve 数组;当 Promise 数组中有一个 Promise reject,返回一个 reject。
Promise.all([promise1, promise2, promise3]) .then(([res1, res2, res3]) => console.log(res1, res2, res3)) .catch(error => console.log(error));
但 Promise.all() 的问题在于一旦发起所有的异步请求,就无法控制它们的并发数量,容易导致请求过多,影响性能。因此,我们需要使用限制并发数量的 Promise 控制器,控制异步请求的执行。
使用 Promise 并发控制器
下面,我们介绍如何使用 Promise 并发控制器实现多个异步请求的并发控制。
首先,我们需要定义一个 Promise 表示异步函数:
function asyncTask() { return new Promise((resolve, reject) => { // 异步任务 }); }
接下来,我们定义一个限制并发数量的 Promise 控制器:
// javascriptcn.com 代码示例 function newPromise(task, limit) { const queue = []; // 正在运行的任务队列 let count = 0; // 当前正在运行的任务数量 let doneCount = 0; // 已完成的任务数量 let resolveAll; // 记录所有任务完成后的 resolve 函数 let rejectAll; // 记录所有任务完成后的 reject 函数 const runTask = async () => { if (doneCount === limit) { resolveAll(); return; } if (count < limit && queue.length > 0) { const run = queue.shift(); count += 1; try { const result = await run(); count -= 1; doneCount += 1; } catch (error) { rejectAll(error); return; } } }; const startTask = () => { resolveAll = null; rejectAll = null; count = 0; doneCount = 0; queue.length = 0; return new Promise((resolve, reject) => { resolveAll = resolve; rejectAll = reject; for (let i = 0; i < limit; i++) { runTask(); } }); }; const addTask = task => { queue.push(task); runTask(); }; return { startTask, addTask, }; }
这个 Promise 控制器使用两个方法:startTask() 和 addTask()。startTask() 开始执行任务,并返回 Promise。addTask() 添加异步任务。
使用 Promise 控制器来实现异步请求的并发控制,代码如下:
// javascriptcn.com 代码示例 const control = newPromise(asyncTask, 5); const urls = []; for (let i = 0; i < 10; i++) { urls.push('https://example.com/api/' + i); } control.startTask() .then(() => console.log('All tasks are done')) .catch(error => console.log(error)); urls.forEach(url => control.addTask(() => fetch(url)));
上面代码中,我们定义了一个包含 10 个 url 的数组,使用 Promise 控制器 control 控制异步请求的执行。同时最大并发数为 5,即每次只有 5 个请求在执行,其余的请求任务被添加到队列中。
总结
使用 Promise 实现多个异步请求的并发控制能够避免过多的异步请求对应用性能的影响。通过控制并发数量,我们可以保证同时执行的异步请求数目合理,提高应用响应速度。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6530a77e7d4982a6eb239d7b