在循环中使用 Promises
Using Promises in a loop
我尝试创建一个加载测试脚本,但我遇到了奇怪的行为
我使用 https://github.com/prisma-labs/graphql-request 模块进行 graphql 请求。
但是我没有看到进程运行进入回调
我看到了下一个结果。它停在前 5 个项目上。
GET: MX
GET: MX
GET: DE
GET: LT
GET: US
我想也许我无法访问回调函数中的 requestCount 变量,但我什至没有看到请求已发送。
import { request, gql } from 'graphql-request'
const MAX_REQUESTS = 5;
const countries = ['GB', 'UK', 'US', 'LT', 'IT', 'DE', 'MX']
const getRandomElement = (items) => {
return items[Math.floor(Math.random()*items.length)];
}
let requestCount = 0;
while (true) {
let country = getRandomElement(countries);
let query = gql`
{
country(code: "${country}") {
name
native
capital
emoji
currency
languages {
code
name
}
}
}`
if (requestCount >= MAX_REQUESTS) {
continue;
}
console.log('GET: ', country);
request('https://countries.trevorblades.com/', query).then((data) => {
console.log('OK: ', country);
requestCount--;
}).catch((error) => {
console.log('FAILED: ', country);
requestCount--;
console.error(error)
})
requestCount++;
}
这是 Node.js(同步)
的行为
如果您有同步的代码段并且其中有异步回调。它将等待同步执行,然后移动到回调队列。
一个简单的例子
let counter = 0;
while(true) {
console.log("While", counter++)
setTimeout(() => {
console.log("Inside Timeout")
}, 0)
}
在您的用例中,您可以维护队列或更改 while 条件
你的 while 循环永远不会中断,它会一直执行并占据进程。您的异步函数 (Promises) 永远没有机会返回线程执行。
修改:每次发送5个项目的请求。
import { request, gql } from "graphql-request";
const MAX_REQUESTS = 5;
const arr = ["GB", "UK", "US", "LT", "IT", "DE", "MX"];
const getRandomElements = (items, numberOfElements) => {
return Array.from({ length: numberOfElements }).map(
_ => items[Math.floor(Math.random() * items.length)]
);
};
const getQuery = country => gql`
{
country(code: "${country}") {
name
native
capital
emoji
currency
languages {
code
name
}
}
}`;
(async function run() {
while (true) {
const countries = getRandomElements(arr, MAX_REQUESTS);
const promises = countries.map(country =>
request("https://countries.trevorblades.com/", getQuery(country))
);
const results = await Promises.allSettled(promises);
results.forEach((res, i) => {
if (res.status === "fulfilled") {
console.log(`OK: Country:${countries[i]} data:${res.value}`);
} else {
console.log(`FAIL: Country:${countries[i]} Error:${res.reason}`);
}
});
}
})();
我尝试创建一个加载测试脚本,但我遇到了奇怪的行为 我使用 https://github.com/prisma-labs/graphql-request 模块进行 graphql 请求。
但是我没有看到进程运行进入回调
我看到了下一个结果。它停在前 5 个项目上。
GET: MX
GET: MX
GET: DE
GET: LT
GET: US
我想也许我无法访问回调函数中的 requestCount 变量,但我什至没有看到请求已发送。
import { request, gql } from 'graphql-request'
const MAX_REQUESTS = 5;
const countries = ['GB', 'UK', 'US', 'LT', 'IT', 'DE', 'MX']
const getRandomElement = (items) => {
return items[Math.floor(Math.random()*items.length)];
}
let requestCount = 0;
while (true) {
let country = getRandomElement(countries);
let query = gql`
{
country(code: "${country}") {
name
native
capital
emoji
currency
languages {
code
name
}
}
}`
if (requestCount >= MAX_REQUESTS) {
continue;
}
console.log('GET: ', country);
request('https://countries.trevorblades.com/', query).then((data) => {
console.log('OK: ', country);
requestCount--;
}).catch((error) => {
console.log('FAILED: ', country);
requestCount--;
console.error(error)
})
requestCount++;
}
这是 Node.js(同步)
的行为如果您有同步的代码段并且其中有异步回调。它将等待同步执行,然后移动到回调队列。
一个简单的例子
let counter = 0;
while(true) {
console.log("While", counter++)
setTimeout(() => {
console.log("Inside Timeout")
}, 0)
}
在您的用例中,您可以维护队列或更改 while 条件
你的 while 循环永远不会中断,它会一直执行并占据进程。您的异步函数 (Promises) 永远没有机会返回线程执行。
修改:每次发送5个项目的请求。
import { request, gql } from "graphql-request";
const MAX_REQUESTS = 5;
const arr = ["GB", "UK", "US", "LT", "IT", "DE", "MX"];
const getRandomElements = (items, numberOfElements) => {
return Array.from({ length: numberOfElements }).map(
_ => items[Math.floor(Math.random() * items.length)]
);
};
const getQuery = country => gql`
{
country(code: "${country}") {
name
native
capital
emoji
currency
languages {
code
name
}
}
}`;
(async function run() {
while (true) {
const countries = getRandomElements(arr, MAX_REQUESTS);
const promises = countries.map(country =>
request("https://countries.trevorblades.com/", getQuery(country))
);
const results = await Promises.allSettled(promises);
results.forEach((res, i) => {
if (res.status === "fulfilled") {
console.log(`OK: Country:${countries[i]} data:${res.value}`);
} else {
console.log(`FAIL: Country:${countries[i]} Error:${res.reason}`);
}
});
}
})();