Skip to content Skip to sidebar Skip to footer

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, an

Solution 1:

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.

Solution 2:

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 readyState4 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: asyncfunction (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 thingsxhr: function () {
        return xhr = newXMLHttpRequest();
    }
};
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);

Solution 3:

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 = newBlob(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);
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Post a Comment for "Jquery: Access Binary Ajax Response Inside Complete Function Or Access Xhr Object Outside Of Callback Functions?"