Fetch API や Blob で UTF-8 以外の文字コードを扱う

# 1. 予備知識

`fetch` で得た `Response` や `Blob` のメソッドはテキストデータの文字コードを常に UTF-8 として扱うため、Shift_JIS 等の UTF-8 以外の文字コードでは文字化けします。

参考「[Response.text() - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/Response/text)」
参考「[Blob.text() - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/Blob/text)」

直接 UTF-8 以外の文字コードを扱うことはできないため、バイナリデータを経由して文字コードを指定してテキストデータに変換します:

- 方法 1: `ArrayBuffer` を経由して `TextDecoder` を用いる
    - `textDecoder.decode(arrayBuffer)`
- 方法 2: `Blob` を経由して `FileReader` を用いる
    - `fileReader.readAsText(blob)`
    - 古いやり方のため、本記事では不説明

参考「[TextDecoder: decode() メソッド - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/TextDecoder/decode)」
参考「[FileReader.readAsText() - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/FileReader/readAsText)」

# 2. テキストの場合

```js
const textDecoder = new TextDecoder('shift-jis');

// 
const responseA = await fetch('data.txt')
const arrayBufferA = await responseA.arrayBuffer();
const textA = textDecoder.decode(arrayBufferA);

console.log(textA);

// 
const responseB = await fetch('data.txt');
const blob = await responseB.blob();
const arrayBufferB = await blob.arrayBuffer();
const textB = textDecoder.decode(arrayBufferB);

console.log(textB);
```

# 3. `JSON` の場合

文字コードを指定する場合は `response.json()` を使えないため、通常のテキストに変換してから `JSON.parse()` を用います。 

```js
const textDecoder = new TextDecoder('shift-jis');

// 
const responseA = await fetch('data.json')
const arrayBufferA = await responseA.arrayBuffer();
const textA = textDecoder.decode(arrayBufferA);
const valueA = JSON.parse(textA);

console.log(valueA);

// 
const responseB = await fetch('data.json');
const blob = await responseB.blob();
const arrayBufferB = await blob.arrayBuffer();
const textB = textDecoder.decode(arrayBufferB);
const valueB = JSON.parse(textB);

console.log(valueB);
```

参考「[Response.json() - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/Response/json)」
参考「[JSON.parse() - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse)」

# 4. XML および HTML の場合

`DOMParser` を併用することで、XML および HTML のテキストデータを DOM として扱うことができます。

```js:XML
const textDecoder = new TextDecoder('shift-jis');

const domParser = new DOMParser();

// 
const responseA = await fetch('data.xml')
const arrayBufferA = await responseA.arrayBuffer();
const textA = textDecoder.decode(arrayBufferA);
const documentA = domParser.parseFromString(textA, 'application/xml');

console.log(documentA);

// 
const responseB = await fetch('data.xml');
const blob = await responseB.blob();
const arrayBufferB = await blob.arrayBuffer();
const textB = textDecoder.decode(arrayBufferB);
const documentB = domParser.parseFromString(textB, 'application/xml');

console.log(documentB);
```

```js:HTML
const textDecoder = new TextDecoder('shift-jis');

const domParser = new DOMParser();

// 
const responseA = await fetch('data.html')
const arrayBufferA = await responseA.arrayBuffer();
const textA = textDecoder.decode(arrayBufferA);
const documentA = domParser.parseFromString(textA, 'text/html');

console.log(documentA);

// 
const responseB = await fetch('data.html');
const blob = await responseB.blob();
const arrayBufferB = await blob.arrayBuffer();
const textB = textDecoder.decode(arrayBufferB);
const documentB = domParser.parseFromString(textB, 'text/html');

console.log(documentB);
```

参考「[DOMParser - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/DOMParser)」

# 5. おまけ: `Response` からメソッドで変換可能なデータ形式について

`Response` からメソッドで変換可能なデータ形式は以下の通りです:

- バイナリデータ
    - `ArrayBuffer`
    - `Blob`
    - `FormData`
- テキストデータ
    - テキスト
    - `JSON`

参考「[メソッド - Response - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/Response#%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)」