Reputation: 9
I am sending a great amount of events in batches of 20 events to an analytics tables in BigQuery. Initially, I used sendBeacon
but switched to using regular POST
requests. Below is the class I use to handle sending events:
import { createControllablePromise, delay } from '../utils/generalUtils';
class EventReporterWorker {
#requestQueue = Promise.resolve();
#activeRequest;
#isPageVisible = true;
#handleSendEvents = async eventsPayload => {
if (this.#isPageVisible) {
await this.#activeRequest;
}
const currentRequestPromise = createControllablePromise();
const cancelTimeout = setTimeout(() => currentRequestPromise.resolve(), 30000);
currentRequestPromise.finally(() => clearTimeout(cancelTimeout));
this.#activeRequest = currentRequestPromise;
const requestPromise = fetch('*MY_URL*, {
method: 'POST',
headers: {
accept: '*/*',
'cache-control': 'no-cache',
'content-type': 'text/plain;charset=UTF-8',
},
body: eventsPayload,
keepalive: true,
mode: 'no-cors', // Matches sendBeacon's behavior
});
requestPromise.finally(() => {
currentRequestPromise.resolve();
});
if (this.#isPageVisible) {
try {
await delay(300);
await requestPromise;
} catch (e) { }
}
};
sendEvents = async eventsPayload => {
const newRequestsQueue = this.#requestQueue.then(() => this.#handleSendEvents(eventsPayload));
this.#requestQueue = newRequestsQueue;
return newRequestsQueue;
};
setPageVisible = isPageVisible => {
this.#isPageVisible = isPageVisible;
if (!isPageVisible) {
this.#activeRequest.resolve();
}
};
}
export const eventReporterWorker = new EventReporterWorker();
I am using promises because I receive events from multiple places and want them to be executed sequentially. The only time I want all the events to be sent immediately is when I switch tabs.
However, when switching tabs, some of the POST
calls fail and stuck on Pending
status.
The error message is:
Uncaught (in promise) TypeError: Failed to fetch
Events before and after this failure succeed, as shown in the image.
Has anyone encountered this issue or have any ideas on how to fix it?
I’ve tried sending events in batches, added delays, checked the server (the issue isn't on the server side), and confirmed that the internet connection is fine. The call seems to fail at the browser level.
Upvotes: 0
Views: 34
Reputation: 180
Seems like you have a similar case here. The "TypeError: Failed to fetch
" error usually occurs for multiple reasons:
An incorrect or incomplete URL has been passed to the fetch() method.
The server you are making a request to does not send back the correct CORS headers.
A wrong protocol is specified in the url.
A wrong method or headers have been passed to the fetch() method.
While keepalive is designed to help with this, it doesn’t guarantee the request will complete. Your mode: 'no-cors' exacerbates the issue because no-cors requests are limited in the information they can return, making it hard to detect actual failures versus browser-terminated requests.
Unless absolutely necessary, avoid no-cors. It severely limits error handling and can hide important information about request failures. Correctly configuring CORS on your server is the recommended approach.
Upvotes: 0