年に1回くらいは必要になりそうだけど絶対に忘れてしまうと思うので、検証済みのコードを自分用に記録しておく。
APIを叩くコードを、IE11でも動くように書く。
何らかの理由で Babel によるトランスパイルが出来ない、したくない状況を想定している。
基本的にスタティックなページだがサイトの更新情報だけAPIで取得して表示したい、というケースなど。
まずコードの全体像を載せる。
(function() { function apiRequest(method, endPoint, body, onSuccess) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if (xhr.status === 200) { onSuccess(JSON.parse(xhr.responseText)); } } }; xhr.open(method, endPoint); xhr.withCredentials = true; xhr.setRequestHeader('Content-Type', 'application/json'); xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhr.send(body ? JSON.stringify(body) : null); } apiRequest( 'POST', 'http://api.example.com/login', {userName: 'admin', password: 'pass'}, function(res) { console.log(res); } ); })();
この内容のファイルを<script src="./ie11.js" defer></script>
という形で読み込ませれば、動く。
DOM操作などがある場合はHTMLのパースが終わってから読み込みたいので、念の為defer
をつける。
参考: qiita.com
apiRequest
に必要な情報を渡して呼び出すことで、リクエストが発生する。
console.log(res);
の部分でapiRequest
を実行すれば、リクエストの結果を受けてまた別のAPIを呼ぶ、ということも出来る。
それを繰り返すとどんどんコールバック地獄になっていくが。
以下、解説。
まず、グローバル汚染を防ぐために、無名関数を実行してそのなかで全ての処理を行う。
アロー関数は使えないので、無名関数もfunction
を使って定義する。以降も同様。
(function() {})();
fetch
はIE11では使えないので、XMLHttpRequest
オブジェクトのインスタンスを作りそれを使って非同期通信を行う。
let
もconst
も使えないので、変数宣言は全てvar
。
var xhr = new XMLHttpRequest();
以降、このインスタンス(今回の例ではxhr
)に対して設定や操作を行っていく。
まずonreadystatechange
。
これには、コールバック関数を渡す。この関数は、readyState
が変わる度に呼び出される。
readyState
は通信状態が変わっていく度に値が変わるが、通信が完了すると4
になる。
なので、xhr.readyState === 4
を条件にして、通信完了時の処理を書けばよい。
status
には、レスポンスのステータスコードが入っている。
今回は通信が成功したときにのみ処理を行うのでxhr.status === 200
のときに、レスポンスを引数にしてonSuccess
を実行している。
xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if (xhr.status === 200) { onSuccess(JSON.parse(xhr.responseText)); } } };
ここらへんの詳しい説明は、MDNにまとまっている。
- https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest/onreadystatechange
- https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest/readyState
- https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest/status
open
で、HTTPメソッドとURLを指定する。
xhr.open(method, endPoint);
withCredentials
をtrue
にすれば、クッキーの送受信も行われる。
xhr.withCredentials = true;
なお、CORSについては設定は不要。fetch
ではmode: 'cors'
の設定が必要だったが、XMLHttpRequest
では何もする必要がない。
独自ヘッダを付与したい場合は、setRequestHeader
を使う。
xhr.setRequestHeader('Content-Type', 'application/json'); xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
send
で、実際にリクエストを送信する。引数が、リクエストボディの値になる。
xhr.send(body ? JSON.stringify(body) : null);