elbywan / wretch

A tiny wrapper built around fetch with an intuitive syntax. :candy:
MIT License
4.83k stars 98 forks source link

I get an error when I try to get an ArrayBuffer #202

Closed kravetsone closed 1 year ago

kravetsone commented 1 year ago
.catcherFallback(async (error) => {
        console.log("errrorrrr", await error.response.arrayBuffer());
    });

When i try to get ArrayBuffer like this i recieve a error:

image

WretchError is

export declare class WretchError extends Error implements WretchErrorType {
    status: number;
    response: WretchResponse;
    url: string;
    text?: string;
    json?: any;
}

how can i get ArrayBuffer?

elbywan commented 1 year ago

Hey @kravetsone,

When i try to get ArrayBuffer like this i recieve a error:

This is expected since wretch already reads the error payload body to fill the WretchError instance for easier consumption. The response body is a stream and can be read only once.

I guess you could try the following:

.catcherFallback(async (error) => {
  console.log("errrorrrr", await new Response(error.text).arrayBuffer());
});
kravetsone commented 1 year ago

maybe a better way would be

.catcherFallback(async (error) => {
  await error.text();
  await error.json();
  await error.arrayBuffer();
});

It's look like work with successful response and more convenient in my opinion

elbywan commented 1 year ago

Wretch parses the response body as a string - or json (depending on the content-type) ahead of time to pre-populate the WretchError fields for convenience and prevent having to perform asynchronous operations after catching it.

I could clone the response body stream to make it consumable twice, but then it would consume more memory.

So I am comfortable with the current way of doing things, since having arrayBuffer/blob error payloads is quite uncommon compared to text/json.

kravetsone commented 1 year ago

in my project, I use protocol buffers and when I follow your example above during deserialization, I get an EOT (End Of File) error, although this does not happen with successful requests.

I do not know what to do(

elbywan commented 1 year ago

You could try using TextDecoder / TextEncoder. It seems to convert between strings and array buffers quite fine.

const arrayBuffer = new Uint8Array([22, 05, 68, 65, 0x6c, 0x6c, 0x6f, 28, 01, 28, 02, 28, 03])
const response = new Response(arrayBuffer)
response
  .text()
  .then(txt => new TextEncoder("utf-8").encode(txt))
  .then(buffer => console.log(buffer))
/* output:
Uint8Array(13) [ 22, 5, 68, 65, 108, 108, 111, 28, 1, 28, … ]
  0: 22
  1: 5
​  2: 68
  ​3: 65
​  4: 108
  ​5: 108
​  6: 111
  ​7: 28
​  8: 1
​  9: 28
​  10: 2
​  11: 28
​  12: 3
*/

In your case, something like:

.catcherFallback(async (error) => {
  const buffer = new TextEncoder("utf-8").encode(error.text)
});
kravetsone commented 1 year ago

Thanks for the quick help! I repeated all the steps and found the problem. The problem was in the wrong way to serialization validation errors)

it's ugly... but it's work! image

By the way, TextEncoder does not accept such a parameter and works with UTF-8 by default. But thanks anyway! image