Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

197
Visualizações
jQuery: access binary AJAX response inside complete function or access XHR object outside of callback functions?

There are many questions on handling binary AJAX responses with jQuery like this, this, and this. None help.

Goals: (1) dynamically determine if a response contains binary data, and handle it differently from text; (2) analyze response headers; and (3) do both from a single function.

Ideally, this can be done from the complete function, but the complete function doesn't have access to the XHR object. jqXHR is supposed to be a superset of the XHR object, but XHR.response is blank.

The return value of $.ajax(settings) contains the binary data, but the XHR object is no longer available -- so it seems not possible to analyze the response headers.

Is it possible to access the binary AJAX response inside the complete callback or access the XHR object outside of the callback functions? The

// Assume @data contains body and URL values.

let settings = {
    url: data.url,
    method: "post",
    timeout: 0,
    contentType: false,
    processData: false,
    data: data.body,
    xhr: function() {
                // Create XMLHttpRequest object.
                let xhr = new XMLHttpRequest();

                // Handle event for when response headers arrive.
                xhr.onreadystatechange = function() {
                    if (xhr.readyState == 2) {
                        if (xhr.status == 200) {
                            xhr.responseType = 'blob';
                        } else {
                            xhr.responseType = 'text';
                        }
                    }
                };

                return xhr;
    },
    complete: function(xhr, status, error) {
        // Can access response headers but not binary response here.
    }
};

let response = await $.ajax(settings);
// @response is blob but cannot access XHR object here.
over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

I assume you're using jQuery v1.5+. The complete callback was deprecated in favor of always, which includes the response body. I could get it, along with the response headers, in a single function doing something like:

$.ajax({
    url: 'https://static.wikia.nocookie.net/5dabc4c4-7cdb-438d-ba57-6b09afffcbb4',
    method: 'get',
})
  .always((responseBody, responseStatus, xhr) => {
    // You don't need this check when using .done()
    if (responseStatus === 'success') {
      if (xhr.getResponseHeader('content-type').startsWith('image')) {
        processImage(responseBody)
      }
    }
  })

This should work in your example too. Let me know if that worked.

over 4 years ago · Santiago Trujillo Relatório

0

I don't know if you are constrained by some archaic version of jQuery, but you can actually do all of that.

The return value of $.ajax(settings) contains the binary data, but the XHR object is no longer available -- so it seems not possible to analyze the response headers.

Technically, no. The return value of $.ajax(settings) is jqXHR object, So you can access the same object that you get within the callbacks. In your code, you are using the async/await pattern, and thus not able to access the jqXHR object. But you can do so

let jqXHR = $.ajax(settings);
jqXHR.then((response) => {
    console.log(response);
    console.log(res.getAllResponseHeaders());
});

This way, you will get both the jqXHR object and the response object.

Ideally, this can be done from the complete function, but the complete function doesn't have access to the XHR object. jqXHR is supposed to be a superset of the XHR object, but XHR.response is blank.

Because you are accessing it at the wrong time. In order for the response property to be populated, you have to wait until readyState 4 instead of 2. Refer to XHR readyState.
Then again, you can get the response object within the complete callback too. Just treat the xhr callback parameter the same way you would do the $.ajax(settings) response.

complete: function(xhr, status, error) {
    res.then((response) => {
        console.log(response);
        console.log(res.getAllResponseHeaders());
    });
}

If you are using the newer versions of jQuery (I guess the last 2-3 year ones), you can even write this neat code

complete: async function (xhr, status, error) {
    console.log(xhr.getAllResponseHeaders());
    console.log(await xhr);
}

And if you literally need the XHR object, you can do this hack too.

let xhr;
let settings = {
    //rest of things
    xhr: function () {
        return xhr = new XMLHttpRequest();
    }
};
let jqXHR = $.ajax(settings);
xhr.onreadystatechange = function() {
    if (xhr.readyState == 2) {
        if (xhr.status == 200) {
            xhr.responseType = 'blob';
        } else {
            xhr.responseType = 'text';
        }
    }
};
let response = await jqXHR;
console.log(response);
over 4 years ago · Santiago Trujillo Relatório

0

In order to dynamically determine the response, it's more convenient to use the success function instead of always or complete (these will also run on error). In it, you get the jqXHR object and you can read the data type that was sent back. After determining that it is binary (in the code below, it's image/png), you can convert the response from text to binary, and optionally put it in a Blob. Like so:

let data = {
    url: "https://www.gravatar.com/avatar/cc0c5253923613abd592330ed8adb3a0?s=48&d=identicon&r=PG",
    body: {}
}
let settings = {
    url: data.url,
    method: "post",
    timeout: 0,
    contentType: false,
    processData: false,
    data: data.body,
    success: function(response, status, jqXHR) {
        var type = jqXHR.getResponseHeader('content-type');
        console.log(response);
        console.log(type);
        if(type === 'image/png'){
            var output = [];
            for (var i = 0; i < response.length; i++) {
                  output.push( response[i].charCodeAt(0).toString(2) + " ");
            }
            output = new Blob(output, {type : type});
            console.log(output);
        }
        else{
            console.log('type is not image/png');
        }
    },
    error: function(jqXHR, textStatus, errorThrown) {
        console.log("an error was encountered", errorThrown);
    }
};

$.ajax(settings);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda