Skip to content

AJAX – Convert returned octet-stream to typed array (Float64Array)

I cannot figure out what I’m doing wrong here. I’m trying to convert a binary stream, returned from an AJAX call, to an array of doubles in JavaScript. Some code: My server PHP returns an octet-stream (array of doubles):

while(logic_code)
{
  $binary .= pack('ddd*', item1, item2, item3);
}

header('Content-type: application/octet-stream');
header('Content-length: ' . strlen($binary));
http_response_code(200);
echo $binary;
exit;

In my webpage I have an AJAX call:

function getData() {
    $.ajax({
        type: 'GET',
        url:  '/my/rest/call/to/above/php/code',
        success: function(data) {
            doSomething(data);
        },
        error: function(data, status, error) {
        }
    });
}

And then my function for processing the returned data from the rest call doSomething(data):

function doSomething(data) {
    // Some code here.
    
    var count = data.length / (8);  // Get number of DOUBLES
    var arr = new Float64Array(data, 0, count);

    console.log(arr);

    // Problem: 'arr' is undefined, or array of 0; but 'count' is non-zero.

    // More code here.
}

The issue I’m facing is that Float64Array doesn’t seem to be converting my data to an array. I get a size of zero and undefined while count is a large number. There are no console errors in Chrome so I’m having a hard time really pinning down what I’m missing. Am I suppose to convert data to an ArrayBuffer first? I have looked at data in a hex editor and confirmed the returned byte stream is the correct array of doubles (64-bit little endian) with correct values.

Answer

The Float64Array constructor expects an ArrayBuffer argument. In order to have the browser interpret the response as such, try

$.ajax({
  url: "/my/rest/call/to/above/php/code",
  method: "GET",
  success: doSomething,
  error: (_, ...err) => console.error(...err),
  xhrFields: {
    responseType: "arraybuffer"
  }
})

The fetch API equivalent would be like this, using the Response.arrayBuffer() method

async function getData() {
  try {
    const res = await fetch("/my/rest/call/to/above/php/code")
    if (!res.ok) {
      throw new Error(`${res.status}: ${await res.text()}`)
    }
    
    doSomething(await res.arrayBuffer())
  } catch (err) {
    console.error(err)
  }
}