等待所有 nodeJS 请求完成并为它们添加一个小的延迟
Waiting for all nodeJS request to be finished and add a small delay to them
我有一个旨在与远程交互的应用程序 API。
我必须发出大约 10000 (10k) 个请求,但速度不能太快以至于反 ddos 保护会阻止我。意味着我需要添加一个小延迟。
代码
var promises = [];
for(var i = 0 ; i < list.length;i++)
{
console.log("checking " + list[i]);
promises.push(doRequest(token,Username));
}
Promise.all(promises).then(function()
{
console.log("done");
},function(err){
console.log("oops");
});
doRequest 看起来像这样:
function doRequest(token,username)
{
var checkUsername = { method: 'GET',
url: link + username,
headers:
{ AUTHORIZATION: 'Bearer ' + token,
Accept: 'application/json' } };
return new Promise(function (resolve, reject)
{
request(checkUsername , function (error, res, body) {
try
{
var json = JSON.parse(body);
if(json.success)
{
resolve(username);
}
else
{
reject(username);
}
}
catch(exception)
{
console.log(body);
reject(exception);
}
});
});
}
似乎每次我到达 JSON.parse(body) 时,它都会崩溃,因为我发送请求的速度太快,以至于远程服务器不会认为我是垃圾邮件机器人,结果在我体内只是未定义或只是代码运行太快导致了同样的事情。
我如何才能挽回这种情况,同时仍然保持我的代码的异步性质,使其仍然相对较快?
答案取决于您想尝试多快。您可以同时执行多少个请求等。这是一个可能的策略。你想考虑这个问题的方式是计算出你被允许发出多少个并发请求,并将工作分解为所有 运行 同时发生的同步块。
// the number of simultaneous requests that wont cause problems
const allowedSimultaneous = 10
// create each chain
const chains = Array(allowedSimultaneous).fill(Promise.resolve())
// now build a synchronous list for each block
list.forEach((item, i) => {
const chainIndex = i % allowedSimultaneous
chains[chainIndex] = chains[chainIndex]
.then(() => doRequest(token, Username))
})
// finally use .all() to catch when all chains are completed
Promise.all(chains).then(() => console.log('done'))
注意:这是未经测试的代码,但希望您能理解。您想要构建一定数量的并发链,每个 运行 一组同步调用。这样可以确保并发请求数始终为 allowedSimultaneous
.
根本不需要延迟,因为只会有 allowedSimultaneous
调用 运行ning,但如果你确实需要某种延迟,你可以在每个 [=13] 之后延迟=]
如果您使用的 Node 版本对于 async/await
来说足够新,这将非常轻松。您可以将您的请求分成几组,等待每个组,暂停(通过等待超时),然后继续。例如:
function getGroups(start, end, list) {
var promises = [];
end = end > list.length ? list.length : end
for (var i = start; i < end; i++) {
console.log("checking " + list[i]);
promises.push(doRequest(i));
}
return Promise.all(promises)
}
function doRequest(i) {
// fake request
return new Promise(resolve => setTimeout(() => resolve(i), 750))
}
async function get(list) {
const group_size = 5
const wait_time = 1500
for (var i = 0; i < list.length; i += group_size) {
console.log("getting group")
let group_result = await (getGroups(i, i + group_size, list))
console.log("results of group: ", group_result)
console.log("Waiting")
await new Promise(resolve => setTimeout(resolve, wait_time))
}
}
let urls = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
get(urls)
如果你只是想在 每个 请求之间放置一个小的延迟,你可以在一个循环中使用 async/await
,比如:
function doRequest(i) {
/* fake request */
console.log("requesting: ", i)
return new Promise(resolve => setTimeout(() => resolve(i), 250))
}
let urls = [0, 1, 2, 3, 4, 5]
async function get() {
let results = []
for (url of urls) {
results.push(await doRequest(url))
await new Promise(resolve => setTimeout(resolve, 200))
}
return results
}
get().then(r => console.log("results: ", r))
当然,您需要进行错误检查等...
NPM 有几个用于限制 promise 的包。这个是最上面的:
我有一个旨在与远程交互的应用程序 API。 我必须发出大约 10000 (10k) 个请求,但速度不能太快以至于反 ddos 保护会阻止我。意味着我需要添加一个小延迟。
代码
var promises = [];
for(var i = 0 ; i < list.length;i++)
{
console.log("checking " + list[i]);
promises.push(doRequest(token,Username));
}
Promise.all(promises).then(function()
{
console.log("done");
},function(err){
console.log("oops");
});
doRequest 看起来像这样:
function doRequest(token,username)
{
var checkUsername = { method: 'GET',
url: link + username,
headers:
{ AUTHORIZATION: 'Bearer ' + token,
Accept: 'application/json' } };
return new Promise(function (resolve, reject)
{
request(checkUsername , function (error, res, body) {
try
{
var json = JSON.parse(body);
if(json.success)
{
resolve(username);
}
else
{
reject(username);
}
}
catch(exception)
{
console.log(body);
reject(exception);
}
});
});
}
似乎每次我到达 JSON.parse(body) 时,它都会崩溃,因为我发送请求的速度太快,以至于远程服务器不会认为我是垃圾邮件机器人,结果在我体内只是未定义或只是代码运行太快导致了同样的事情。
我如何才能挽回这种情况,同时仍然保持我的代码的异步性质,使其仍然相对较快?
答案取决于您想尝试多快。您可以同时执行多少个请求等。这是一个可能的策略。你想考虑这个问题的方式是计算出你被允许发出多少个并发请求,并将工作分解为所有 运行 同时发生的同步块。
// the number of simultaneous requests that wont cause problems
const allowedSimultaneous = 10
// create each chain
const chains = Array(allowedSimultaneous).fill(Promise.resolve())
// now build a synchronous list for each block
list.forEach((item, i) => {
const chainIndex = i % allowedSimultaneous
chains[chainIndex] = chains[chainIndex]
.then(() => doRequest(token, Username))
})
// finally use .all() to catch when all chains are completed
Promise.all(chains).then(() => console.log('done'))
注意:这是未经测试的代码,但希望您能理解。您想要构建一定数量的并发链,每个 运行 一组同步调用。这样可以确保并发请求数始终为 allowedSimultaneous
.
根本不需要延迟,因为只会有 allowedSimultaneous
调用 运行ning,但如果你确实需要某种延迟,你可以在每个 [=13] 之后延迟=]
如果您使用的 Node 版本对于 async/await
来说足够新,这将非常轻松。您可以将您的请求分成几组,等待每个组,暂停(通过等待超时),然后继续。例如:
function getGroups(start, end, list) {
var promises = [];
end = end > list.length ? list.length : end
for (var i = start; i < end; i++) {
console.log("checking " + list[i]);
promises.push(doRequest(i));
}
return Promise.all(promises)
}
function doRequest(i) {
// fake request
return new Promise(resolve => setTimeout(() => resolve(i), 750))
}
async function get(list) {
const group_size = 5
const wait_time = 1500
for (var i = 0; i < list.length; i += group_size) {
console.log("getting group")
let group_result = await (getGroups(i, i + group_size, list))
console.log("results of group: ", group_result)
console.log("Waiting")
await new Promise(resolve => setTimeout(resolve, wait_time))
}
}
let urls = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
get(urls)
如果你只是想在 每个 请求之间放置一个小的延迟,你可以在一个循环中使用 async/await
,比如:
function doRequest(i) {
/* fake request */
console.log("requesting: ", i)
return new Promise(resolve => setTimeout(() => resolve(i), 250))
}
let urls = [0, 1, 2, 3, 4, 5]
async function get() {
let results = []
for (url of urls) {
results.push(await doRequest(url))
await new Promise(resolve => setTimeout(resolve, 200))
}
return results
}
get().then(r => console.log("results: ", r))
当然,您需要进行错误检查等...
NPM 有几个用于限制 promise 的包。这个是最上面的: