JavaScript使用Promise控制并发请求
开篇
在现代Web开发中,异步请求已经成为了必不可少的一部分。然而,当我们需要同时处理多个请求时,如何避免请求之间的冲突和混乱呢?这就是今天我们要探讨的话题——如何使用Promise控制并发请求。
在JavaScript中可以通过Promise.all()、Promise.race()、async/await等不同方式来实现对异步并发任务的控制。以下是一种使用Promise.all()方法实现并发控制的示例:
Promise.all()
const urls = ["url1", "url2", ... ,"url100"]; const maxConcurrentNum = 10; // 最大并发数 // 数组分块,chunk表示每批次数量,返回数组二维数组 function chunk(arr, chunk) { let result = []; for (let i = 0, len = arr.length; i < len; i += chunk) { result.push(arr.slice(i, i + chunk)); } return result; } // 异步请求方法 function fetchUrl(url) { return new Promise((resolve, reject) => { fetch(url) .then(res => resolve(res)) .catch(err => reject(err)); }); } // 对url数组进行分块处理 const chunkedUrls = chunk(urls, maxConcurrentNum); (async function () { try { for (let urls of chunkedUrls) { const promises = urls.map(url => fetchUrl(url)); // 等待所有promises完成执行,并将结果存入results数组中 const results = await Promise.all(promises); console.log('results:', results); } } catch (err) { console.error(err); } })();
以上代码通过将数组分成多个数目相等的小数组,每次最多只开启maxConcurrentNum个并发请求,以此来控制并发数量。每当一组请求完成后再发送新的一批请求,可以实现对异步任务的并发控制。
Promise.race()
以下是使用Promise.race()方法来控制并发的示例代码:
const promiselist = []; for (let i = 0; i < 100; i++) { const promise = fetch(`https://example.com/data${i}.json`); promiselist.push(promise); } Promise.race(promiselist) .then(response => { // handle the fastest response here }) .catch(error => { console.error(error); });
async/await
以下是使用async/await方式控制并发请求的示例代码:
async function getData() { const promiselist = []; for (let i = 0; i < 100; i++) { const promise = fetch(`https://example.com/data${i}.json`); promiselist.push(promise); } const responses = await Promise.all(promiselist); for (const response of responses) { // handle each response here } } getData().catch(error => { console.error(error); });
在上面的代码中,我们首先创建了一个async函数,并在该函数中使用for循环来发送所有的请求,并将每个请求的Promise对象存储在一个数组中。 然后,我们使用await关键字来异步等待所有Promise对象都被解决,并将解决值存储在一个数组中。 最后,我们在处理每个响应时对数组进行迭代。
如果我们只需要等待最快的请求,我们可以使用Promise.race()方法,并将其包装在一个async函数中。 这种方法与使用Promise.all()的方式相似,只需使用不同的Promise方法即可。
以下是使用async/await方式控制并发请求的示例代码,其中使用Promise.race()方法:
async function getData() { const promiselist = []; for (let i = 0; i < 100; i++) { const promise = fetch(`https://example.com/data${i}.json`); promiselist.push(promise); } const response = await Promise.race(promiselist); // handle the fastest response here } getData().catch(error => { console.error(error); });
在上述代码中,我们使用async函数来生成Promise对象,然后使用Promise.race()方法等待最快的解决Promise对象,并处理其解决值。
除了Promise.all()和Promise.race()以及async/await等方法外,还有其他用于控制并发请求的可行方法,例如:
手动控制计数器
可以使用变量来手动计数,以控制请求并发数。例如,在循环中,当计数器达到最大并发请求数时,将其用于等待请求完成,然后递增计数器以允许下一个请求。
以下是手动控制计数器的示例代码:
function getData() { const limit = 5; // maximum concurrent requests const dataUrls = ['https://example.com/data1.json', 'https://example.com/data2.json', 'https://example.com/data3.json', 'https://example.com/data4.json', 'https://example.com/data5.json', 'https://example.com/data6.json']; let counter = 0; const getDataPromise = dataUrl => { return new Promise((resolve, reject) => { fetch(dataUrl) .then(response => { counter--; resolve(response); }) .catch(error => { counter--; reject(error); }); }); }; const getDataPromises = dataUrls.map(dataUrl => { if (counter < limit) { counter++; return getDataPromise(dataUrl); } else { return new Promise(resolve => { const interval = setInterval(() => { if (counter < limit) { counter++; clearInterval(interval); resolve(getDataPromise(dataUrl)); } }, 100); }); } }); Promise.all(getDataPromises) .then(responses => { for (const response of responses) { // handle each response here } }) .catch(error => { console.error(error); }); } getData();
在上面的代码中,我们手动地使用计数器来控制最大并发请求数,然后使用setInterval函数来等待可用的请求槽位。
使用第三方库
此外,还有一些第三方库可以使用,例如async.js和p-limit等。p-limit是一个专门用于控制Promise并发的小型库。可以在p-limit文档中找到更多信息和示例。
总结
通过掌握Promise的使用,我们可以轻松应对并发请求,让我们的Web应用更加流畅,用户更加满意。所以,别让并发请求成为你的噩梦,让Promise来帮你解决吧!
到此这篇关于JavaScript使用Promise控制并发请求的文章就介绍到这了,更多相关Promise控制并发请求内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
JavaScript 引用类型实例详解【数组、对象、严格模式等】
这篇文章主要介绍了JavaScript 引用类型,结合实例形式详细分析了JavaScript 数组、对象、严格模式引用类型相关概念、原理及操作注意事项,需要的朋友可以参考下2020-05-05Bootstrap 模态对话框只加载一次 remote 数据的完美解决办法
前端框架 Bootstrap 的模态对话框,可以使用 remote 选项指定一个 URL,这样对话框在第一次弹出的时候就会自动从这个地址加载数据到 .modal-body 中,但是它只会加载一次,不过通过在事件中调用 removeData() 方法可以解决这个问题,具体操作方法,大家通过本文了解下吧2017-07-07
最新评论