Home > Enterprise >  Uncaught errors by .catch clause in Promise for JSON HTTP request
Uncaught errors by .catch clause in Promise for JSON HTTP request

Time:04-30

I have this function that collects JSON data from an API endpoint:

  export const getDataAPI = (token_id) => {
  const url = `https://api.url.com/tokens/`   token_id;
  const options = {method: 'GET', headers: {Accept: 'application/json'}};
  const request = fetch(url, options)
    .then(response => { if (response.status === 200) {
        return response.json();
      } else if ([404, 429, 500].includes(response.status)) {
        return response.status;
      } else {
        return response.json()
          .then(json => {
            console.log("Error: getDataAPI response status", response.status);
            throw json;
          })
      }
    })
    .catch(error => { throw error; });
  return Promise.resolve(request);
};

I have collected over 1.3M records with this function. I would like to catch any unexpected problems so I can gracefully pause for a few seconds and try again. But I came across 2 errors that were not sent to the .catch clause. Even if response is empty / null / undefined, I would expect at least to see the output of console.log("Error: getDataAPI response status", response.status); These errors only happened once each.

undefined:1

SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at Response.json (file:///home/user/node_modules/node-fetch/src/body.js:149:15)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async file:///home/user/path/to/file.mjs:94:20
file:///home/user/node_modules/node-fetch/src/index.js:108
            reject(new FetchError(`request to ${request.url} failed, reason: ${error.message}`, 'system', error));
                   ^

FetchError: request to https://api.url.com/tokens/29727608 failed, reason: read ECONNRESET
    at ClientRequest.<anonymous> (file:///home/user/node_modules/node-fetch/src/index.js:108:11)
    at ClientRequest.emit (node:events:526:28)
    at TLSSocket.socketErrorListener (node:_http_client:442:9)
    at TLSSocket.emit (node:events:526:28)
    at emitErrorNT (node:internal/streams/destroy:157:8)
    at emitErrorCloseNT (node:internal/streams/destroy:122:3)
    at processTicksAndRejections (node:internal/process/task_queues:83:21) {
  type: 'system',
  errno: 'ECONNRESET',
  code: 'ECONNRESET',
  erroredSysCall: 'read'
}
  1. I don't understand why these errors were not caught by the function. Can someone please explain this?

  2. How can I fix the function so it also catches this sort of errors?

  3. What is the output I should be looking for to identify these errors, SyntaxError and FetchError? Is there a variable to monitor for error codes for example?

CodePudding user response:

I would expect at least to see the output of console.log("Error: getDataAPI response status", response.status);

That code isn't in a catch clause, it's in a then clause.

return response.json()
          .then(json => {
            console.log("Error: getDataAPI response status", response.status);
            throw json;
          })

Your catch is simply rethrowing:

.catch(error => { throw error; });

Which will give you an uncaught error.

You need to log/handle the error in the catch, not the then clause:

 export const getDataAPI = (token_id) => {
  const url = `https://api.url.com/tokens/`   token_id;
  const options = {method: 'GET', headers: {Accept: 'application/json'}};
  const request = fetch(url, options)
    .then(response => { if (response.status === 200) {
        return response.json();
      } else if ([404, 429, 500].includes(response.status)) {
        return response.status;
      } else {
        console.log("Error: getDataAPI response status", response.status);
        // you can swallow the error here if you want, or try to parse it anyway
        return response.json()
      }
    })
    .catch(error => { 
       console.log('Handling error', error);
       throw error;
    });

  // wrapping the request in a Promise.resolve is also unnecessary 
  // return Promise.resolve(request);
  return request;
};
 

CodePudding user response:

I'm not sure but are you sure that the API returns a well formatted JSON ?

Or could you surround with try catch the return response.json() ?

CodePudding user response:

Yes I didn't saw that, the .then should goes in a different place ..

  export const getDataAPI = (token_id) => {
  const url = `https://api.url.com/tokens/`   token_id;
  const options = {method: 'GET', headers: {Accept: 'application/json'}};
  const request = fetch(url, options)
    .then(response => { if (response.status === 200) {
        return response.json();
      } else if ([404, 429, 500].includes(response.status)) {
        return response.status;
      } else {
        return response.json()
      }
    }).then(json => {
            console.log("Error: getDataAPI response status", response.status);
            throw json;
          }).catch(error => { throw error; });
  return Promise.resolve(request);
};
  • Related