访问 Promise.allSettled 响应 属性 值。如何?

Accessing Promise.allSettled response property value. How?

自从 Deno 将 javascript/typescript 带到桌面后,我决定创建一个小工具来对 PHP-CGI 网关处理 .php NGINX 文件进行压力测试。

这对 html 仅静态站点会被罚款,但似乎包含状态 502: Gateway Timeout 的获取响应的承诺仍被视为 fulfilled,因此打破了我创建的逻辑。这实际上没问题,因为 NGINX 只是告诉你 PHP-CGI 已关闭,而不是 NGINX。

响应包含我创建所需逻辑所需的值,但我似乎无法访问它。

我使用的代码:

/***
 *  ACME HTTP PHP Gateway Stress Tester 5000
 * 
 */
let promises: Promise<any>[] = [];
let fulfilled: number = 0;
let rejected: number = 0;

const requestCount: number = 1000;  // linear/procedural
const parallelCount: number = 100; // parallel/procedural

const fetchUrl: string = 'http://localhost/info.php';

// Fetch payload (GET)
// Null because url instead
const fetchPayload: any = null;

// Fetch options (GET)
const fetchOptions: any = {
  method: 'GET',
  headers: {
    'Accept': '*/*'
  }
};

console.clear();

console.log(`
/***
 * ACME HTTP Stress Tester 5000
 * 
 * Stress test started... please wait.
 * 
 */
`)

let requestCounter: number = 0;

// Request counter...
for (let rc = 0; rc < requestCount; ++rc) {

  requestCounter++;

  // Parallel counter...
  for (let pc = 0; pc < parallelCount; ++pc) {
    // Push fetch calls into Promise array of promises
    promises.push(fetch(fetchUrl, fetchOptions));
  }

  // Execute fetch calls in Parallel
  await Promise.allSettled(promises).then((results) => {

    results.forEach((result) => {

      console.log(result.value); // <--- ERROR HERE

      if(result.status == 'fulfilled') fulfilled++; // Fulfilled counter
      if(result.status == 'rejected') rejected++;   // Rejected counter
    });

    // Debug output
    console.log(' Wave #         :', requestCounter);
    console.log(' Total Requests :', results.length);
    console.log(' Total Fulfilled:', fulfilled);
    console.log(' Total Rejected :', rejected);
    console.log('— — — — — — — — — — — — — — — — — — — — ')

    /***
     *  Reset these global vars on every new request
     *  containing 1,000 parallel fetch calls
     * 
     */
    promises  = [];
    fulfilled = 0;
    rejected  = 0;

  });

}

console.log(' Stress Test complete.');

我得到的回复:

注意两个不同的 status,一个 fulfilled 和一个 502。我需要访问 502 状态。

{
  status: "fulfilled",
  value: Response {
    body: ReadableStream {
      locked: false
    },
    bodyUsed: false,
    headers: Headers {
      connection: "keep-alive",
      "content-length": "10001",
      "content-type": "text/html; charset=utf-8",
      date: "Fri, 31 Dec 2021 05:53:39 GMT",
      etag: '"61bed520-2711"',
      "feature-policy": "autoplay 'none'; camera 'none'",
      "referrer-policy": "no-referrer-when-downgrade",
      server: "nginx",
      "x-content-type-options": "nosniff",
      "x-frame-options": "SAMEORIGIN",
      "x-xss-protection": "1; mode=block"
    },
    ok: false,
    redirected: false,
    status: 502,
    statusText: "Bad Gateway",
    url: "http://localhost/info.php"
  }
}

如果您显示的输出来自 console.log(result.value),请注意返回数据的结构。那里没有两个 status 字段。一个是 result.value.status: 'fulfilled' 另一个是 result.value.value.status: 502.

如果你把它分解成这样的变量可能会更清楚:

results.forEach((result) => {
  // console.log(result.value); // <--- ERROR HERE
  const obj = result.value;
  console.log(`status is ${obj.status}`);
  console.log(`response status code is ${obj.value.status}`);

  if(obj.status == 'fulfilled') fulfilled++; // Fulfilled counter
  if(obj.status == 'rejected') rejected++;   // Rejected counter
});

请注意,实现 Promise 并不意味着 API 调用有效。这意味着您已成功收到呼叫的回复。响应本身可能仍然失败(在这种情况下出现 502 错误 - 网关错误)但 Promise 仍然实现。如果您只关心 Promise 是否实现(已解决)或被拒绝,那么您所拥有的就是正确的。但是如果你想计算它的调用是否有效,那么你可能应该这样做:

results.forEach((result) => {
  
  if(result.status == 'fulfilled' && result.value.status == 200) {
    fulfilled++; // Fulfilled counter
    console.log(result.value.status);
  }
  if(result.status == 'fulfilled' && result.value.status == 502) {
    rejected++; // Rejected counter
    console.log(result.value.status);
  }
  if(result.status == 'rejected') {
    rejected++;   // Rejected counter
  }
  
});

通常我们更关心实际结果,而不是实现了多少承诺。