web-dev-qa-db-fra.com

Définir XMLHttpRequest.responseType interdit tout d'un coup?

J'utilise XMLHttpRequest synchrone avec responseType défini sur "arraybuffer" depuis un bon moment pour charger un fichier binaire et attendre jusqu'à ce qu'il soit chargé. Aujourd’hui, j’ai eu l’erreur suivante: «Les réponses aux types de réponses de XMLHttpRequest sont synchronisées avec les mods de la fenêtre, mais n’ont plus rien.» ce qui se traduit approximativement par "L'utilisation de responseType pour XMLHttpRequest en mode synchrone dans le contexte de fenêtre (?) n'est plus prise en charge".

Est-ce que quelqu'un sait comment réparer ceci? Je ne veux vraiment pas utiliser une requête asynchrone pour quelque chose comme ça.

var xhr = new XMLHttpRequest();
xhr.open('GET', url, false);
xhr.responseType = 'arraybuffer';

Fonctionne bien en chrome.

18
Markus

C'est un comportement correct, tel que défini dans la spécification de XMLHttpRequest :

Lorsque défini: lève un "InvalidAccessError" exception si le synchrone flag est défini et qu'un document XMLHttpRequest associé .

La propriété responseType ne peut pas être définie lorsque XMLHttpRequest n'est pas asynchrone, c'est-à-dire synchrone. Si vous définissez le troisième paramètre de open sur false, la demande sera synchrone .

12
Rob W

Workaround

Pour le lecteur occasionnel, si vous avez toujours besoin du comportement synchrone, vous pouvez télécharger votre contenu sous forme de chaîne, puis le convertir en données d'octet.

NOTA:
Cette solution de contournement suppose que le request.response d'origine est un texte ASCII.
Si cette hypothèse ne correspond pas à votre cas d'utilisation spécifique, veuillez consulter jBinary .

Je le convertis en ArrayBuffer.

var request = new XMLHttpRequest();
request.open('GET', url, false);
request.send(null);

var data;
if (request.status === 200) {
    data = stringToArrayBuffer(request.response);
} else {
    alert('Something bad happen!\n(' + request.status + ') ' + request.statusText);
}

// ...

function stringToArrayBuffer(str) {
    var buf = new ArrayBuffer(str.length);
    var bufView = new Uint8Array(buf);

    for (var i=0, strLen=str.length; i<strLen; i++) {
        bufView[i] = str.charCodeAt(i);
    }

    return buf;
}

Plus de lecture

  • jBinary : API de haut niveau permettant de travailler avec des données binaires en Javascript.
  • Envoi et réception de données binaires : Traitement de données binaires avec Javascript Javascript. (Source: Réseau de développeurs Mozilla)

Références

8
Stephan

Si vous avez la chance de pouvoir contrôler le point d’entrée de la page entière, envisagez d’envelopper le tout avec une fonction async et d’utiliser await pour bloquer le code asynchrone problématique. Peut ne pas fonctionner avec tous les cas d'utilisation cependant.

(async function () {
    await problem_function_1();
    await problem_function_2();
    ... normal page logic pasted here ...
})(); 

Enveloppez le code asynchrone qui n'est pas une promesse avec une Promise (afin que wait fonctionne comme prévu), puis appelez la fonction de résolution manuellement dans tout ce qui constitue un "rappel de réussite". Faites de même pour rejeter si possible.

0
ThrowawayDart