简体   繁体   中英

Accessing Promise.allSettled response property value. Why am I getting an error?

Since Deno brings javascript/typescript to desktop, I've decided to create a little tool to stress test the PHP-CGI gateway processing .php files for NGINX.

This worked fined for html static only sites but it seems a promise containing a fetch response of status 502: Gateway Timeout is still considered fulfilled thus breaking the logic I've created. This is actually ok since NGINX is just telling you that PHP-CGI is down, not NGINX.

The response contains the value I need to create the logic I want but I can't seem to access it.

The code I am using:

/***
 *  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.');

The response I am getting:

Notice the 2 different status one fulfilled & one 502 . I need to access the 502 status.

{
  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"
  }
}

If the output you show is from console.log(result.value) then note the structure of the data coming back. There are not two status fields there. One is result.value.status: 'fulfilled' and the other is result.value.value.status: 502 .

It might be more clear if you break it into variables like this:

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
});

Note that having the Promise fulfilled doesn't mean the API call worked. It means that you successfully got a response from your call. The response itself might still have failed (in this case with a 502 error - bad gateway) but the Promise still fulfilled. If all you care to count is if the Promise fulfilled (resolved) or rejected, then what you have is correct. But if you want to count whether the call it was making worked, then you should probably do something like this:

results.forEach((result) => {
  // console.log(result.value); // <--- ERROR HERE
  const obj = result.value;
  const responseStatus = obj.value.status;

  if(obj.status == 'fulfilled' && responseStatus === 200) {
    worked++;   // call was successful
  } else {
    failed++;   // call failed with either promise rejection or an error
  }
});

Usually we care more about the actual result rather than how many promises resolved.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM