在循环中使用 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}`);
      }
    });
  }
})();