Kapp-Hamburg
Web-Entwicklung & Hosting – Thorben Nissen

Safari: AJAX-Bug mit `fetch`

Wenn man alte Browser wie den Internet Explorer nicht mehr unterstützen muss, kann man endlich neue Technologien einsetzten. Blöd ist es nur, wenn man dann gerade an einem modernen Browser scheitert.

In meinem Fall habe ich die ersten Versuche mit fetch gemacht. Bei fetch handelt es sich quasi um den Nachfolger des XMLHttpRequests, auch wenn fetch noch das ein oder andere fehlt, um ein vollständiger Ersatz zu sein. Grundsätzlich ist die Syntax aber deutlich besser und fetch nutzt Promises.

In meinem konkreten Fall wollte ich ein Formular per fetch versenden. Dieses Formular enthält u.a. ein Feld für Datei-Uploads. Der Effekt, den ich im Safari feststellen konnte war, dass der Request endlos lief, aber niemals beim Server ankam, also offenbar vom Browser nie wirklich verschickt wurde. Das trat aber nur dann auf, wenn das Feld für Datei-Uploads keine Dateien enthielt. Sobald Dateien ausgewählt waren, hat auch der Safari den Request einwandfrei raus geschickt.

Nach ein wenig Recherche kam ich zu dem Ergebnis, dass die einzige Möglichkeit dieses Problem zu umgehen, die Deaktivierung des Datei-Feldes ist. Anbei ein Code-Snippet als Beispiel.

let formElementFiles = form.querySelector('[name="files[]"]');
// If no files are to be uploaded, disable the file field during initialization
// of FormData to make `fetch` work in Safari
if (formElementFiles && formElementFiles.files.length === 0) {
    formElementFiles.setAttribute('disabled', 'disabled');
}
let formData = new FormData(form);
// Re-enable the file field again
if (formElementFiles && formElementFiles.files.length === 0) {
    formElementFiles.removeAttribute('disabled');
}
fetch(url, {
    method: 'POST',
    // ....
});