Setting XMLHttpRequest.responseType forbidden all of a sudden?

31,367

Solution 1

This is correct behaviour, as defined in the Specification of XMLHttpRequest:

When set: throws an "InvalidAccessError" exception if the synchronous flag is set and there is an associated XMLHttpRequest document.

The responseType property cannot be set when the XMLHttpRequest is not async, that is, synchronous. Setting the third parameter of open to false causes the request to be synchronous.

Solution 2

Workaround

For the casual reader, if you still need the synchronous behavior, you can download your content as string and then convert it to byte data

NOTA:
This workaround assumes the original request.response is an ASCII text.
If this assumption doesn't fit your specific use case please see jBinary.

I convert it to an 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;
}

More reading

References

Solution 3

As it's not possible to set responseType = 'arraybuffer' in sync mode, receiving string and converting to bytes is a solution, but as Stephan said, your data should be an ascii text. You will receive wrong value (253) instead of all bytes above 127.

But setting mime-type and charset to x-user-defined might be a solution:

Here server send 10 bytes from 125 to 134:

request = new XMLHttpRequest();
request.overrideMimeType('text/plain; charset=x-user-defined');
request.open('GET', url, false);
request.send();
Uint8Array.from(request.response, c => c.charCodeAt(0));
> Uint8Array(10) [125, 126, 127, 128, 129, 130, 131, 132, 133, 134]

without setting mime-type it's like this:

request = new XMLHttpRequest();
request.open('GET', url, false);
request.send();
Uint8Array.from(request.response, c => c.charCodeAt(0));
> Uint8Array(10) [125, 126, 127, 253, 253, 253, 253, 253, 253, 253]
Share:
31,367

Related videos on Youtube

Markus
Author by

Markus

Updated on September 17, 2020

Comments

  • Markus
    Markus over 3 years

    I've been using synchronous XMLHttpRequest with responseType set to "arraybuffer" for quite a while to load a binary file and wait until it is loaded. Today, I got this error: "Die Verwendung des responseType-Attributes von XMLHttpRequest wird im synchronen Modus im window-Kontekt nicht mehr unterstützt." which roughly translates to "Usage of responseType for XMLHttpRequest in synchronous mode in window-context(?) no longer supported."

    Does anyone know how to fix this? I realy don't want to use an asynchronous request for something like this.

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

    Works fine in chrome.

    • Janus Troelsen
      Janus Troelsen about 11 years
      You can do binary synchronous XHR's in Web Workers...
  • Markus
    Markus about 12 years
    Sounds weird to me that something like that is supposed to throw an exception. But thanks for pointing me to the specification.
  • Boris Zbarsky
    Boris Zbarsky about 12 years
    @Markus The point is that you shouldn't be writing new code that uses sync XHR. Removing it altogether would break existing sites, but browsers and the spec are trying to restrict its use in new code so that new code actually does the right thing and uses async XHR.
  • Tamas Hegedus
    Tamas Hegedus about 8 years
    Is there a way to retrieve the original binary (non-ascii) binary data exactly?
  • Stephan
    Stephan about 8 years
    @TamasHegedus To answer your question, I have updated my post with a More reading section.
  • Tamas Hegedus
    Tamas Hegedus about 8 years
    I am suspicious about the binary-text-binary conversion not yielding the original bytes
  • Stephan
    Stephan almost 7 years
    @TamasHegedus The workaround presented here works only with the assumption the original bytes are encoded in ASCII.