Browse Source

feat(ui): Catch and ignore failed requests (#34749)

Unintentionally removed the catch in https://github.com/getsentry/sentry/pull/34653, but we should catch and ignore when fetch fails (e.g. cancellations).
Billy Vong 2 years ago
parent
commit
58ea96552f
1 changed files with 59 additions and 55 deletions
  1. 59 55
      static/app/api.tsx

+ 59 - 55
static/app/api.tsx

@@ -445,71 +445,75 @@ export class Client {
 
     // XXX(epurkhiser): We migrated off of jquery, so for now we have a
     // compatibility layer which mimics that of the jquery response objects.
-    fetchRequest.then(async response => {
-      // The Response's body can only be resolved/used at most once.
-      // So we clone the response so we can resolve the body content as text content.
-      // Response objects need to be cloned before its body can be used.
-      const responseClone = response.clone();
-
-      let responseJSON: any;
-      let responseText: any;
-
-      const {status, statusText} = response;
-      let {ok} = response;
-      let errorReason = 'Request not OK'; // the default error reason
-
-      // Try to get text out of the response no matter the status
-      try {
-        responseText = await response.text();
-      } catch (error) {
-        ok = false;
-        if (error.name === 'AbortError') {
-          errorReason = 'Request was aborted';
-        } else {
-          errorReason = error.toString();
-        }
-      }
+    fetchRequest
+      .then(async response => {
+        // The Response's body can only be resolved/used at most once.
+        // So we clone the response so we can resolve the body content as text content.
+        // Response objects need to be cloned before its body can be used.
+        const responseClone = response.clone();
 
-      const responseContentType = response.headers.get('content-type');
-      const isResponseJSON = responseContentType?.includes('json');
+        let responseJSON: any;
+        let responseText: any;
 
-      const isStatus3XX = status >= 300 && status < 400;
-      if (status !== 204 && !isStatus3XX) {
+        const {status, statusText} = response;
+        let {ok} = response;
+        let errorReason = 'Request not OK'; // the default error reason
+
+        // Try to get text out of the response no matter the status
         try {
-          responseJSON = await responseClone.json();
+          responseText = await response.text();
         } catch (error) {
+          ok = false;
           if (error.name === 'AbortError') {
-            ok = false;
             errorReason = 'Request was aborted';
-          } else if (isResponseJSON && error instanceof SyntaxError) {
-            // If the MIME type is `application/json` but decoding failed,
-            // this should be an error.
-            ok = false;
-            errorReason = 'JSON parse error';
+          } else {
+            errorReason = error.toString();
           }
         }
-      }
 
-      const responseMeta: ResponseMeta = {
-        status,
-        statusText,
-        responseJSON,
-        responseText,
-        getResponseHeader: (header: string) => response.headers.get(header),
-      };
-
-      // Respect the response content-type header
-      const responseData = isResponseJSON ? responseJSON : responseText;
-
-      if (ok) {
-        successHandler(responseMeta, statusText, responseData);
-      } else {
-        globalErrorHandlers.forEach(handler => handler(responseMeta));
-        errorHandler(responseMeta, statusText, errorReason);
-      }
+        const responseContentType = response.headers.get('content-type');
+        const isResponseJSON = responseContentType?.includes('json');
 
-      completeHandler(responseMeta, statusText);
-    });
+        const isStatus3XX = status >= 300 && status < 400;
+        if (status !== 204 && !isStatus3XX) {
+          try {
+            responseJSON = await responseClone.json();
+          } catch (error) {
+            if (error.name === 'AbortError') {
+              ok = false;
+              errorReason = 'Request was aborted';
+            } else if (isResponseJSON && error instanceof SyntaxError) {
+              // If the MIME type is `application/json` but decoding failed,
+              // this should be an error.
+              ok = false;
+              errorReason = 'JSON parse error';
+            }
+          }
+        }
+
+        const responseMeta: ResponseMeta = {
+          status,
+          statusText,
+          responseJSON,
+          responseText,
+          getResponseHeader: (header: string) => response.headers.get(header),
+        };
+
+        // Respect the response content-type header
+        const responseData = isResponseJSON ? responseJSON : responseText;
+
+        if (ok) {
+          successHandler(responseMeta, statusText, responseData);
+        } else {
+          globalErrorHandlers.forEach(handler => handler(responseMeta));
+          errorHandler(responseMeta, statusText, errorReason);
+        }
+
+        completeHandler(responseMeta, statusText);
+      })
+      .catch(() => {
+        // Ignore all failed requests
+      });
 
     const request = new Request(fetchRequest, aborter);
     this.activeRequests[id] = request;