師走

この記事はオールアバウトアドベントカレンダー 9日目の記事になります。

#「師走」
この意味を皆さんは知っているでしょうか？
師 = 坊さんが、走るくらい忙しい季節。というのが一般的だとは思いますが、所々説があるようです。

**「し・果す」説**
「し・果す」説とは師走を「し」が「果す」ととらえるという意味で、つまりは「し」が終わるという説のことを指します。
「し」とは「仕事」や「四季」、「年」を意味しており、一年の最後の月という意味合いが強いのがこの説の特徴です。

**…というわけで、早いものでもう師走です。**
今年も一年色々とあったわけですが、仕事上ハマったことの一部をまとめて、解決方法含めつらつらと書きたいと思います。

ちなみに去年、こんな記事を書きました。

[パズドレンダー](http://qiita.com/m_miura/items/e2437f929762ef815c82)

余談続きで申し訳ないですが、今年も引き続きパズドラをやっています。
今のリーダーはこれ。

![003d848abb93a8eb63798f7714fff564.jpg](https://allabout.qiita.com/files/d69962da-67f6-46cc-b494-d22d7d101695.jpeg)


さて、屁のつっぱりはいらんですよ！(古い)という声が聞こえてきそうなので、これくらいにして本題に。

# ハマったこと
今年は、AllAboutの広告配信周りのお仕事に従事させて頂きました。
広告って配信するまでに色々と気を使わないといけない事がありまして…。
中でも特にハマったこと２つを紹介したいと思います。

## 1. 非同期通信
javascriptのお話です。
非同期通信。これ皆さんもうご存知だと思います。今更何をはまってんだと。
配信する広告の内容（クリエイティブ）を取得するAPIのリクエストは非同期で通信を行い、他のリクエストを邪魔しないようにしていました。

```php:sample.html
<script type="text/javascript" src="hoge.js">
</head>

～ 省略 ～

<script type="text/javascript">
// ここで処理を発火 内部で非同期に通信を行いクリエイティブを返す
new getAd();
</script>
```

大雑把に言うと、全体的にはこんな感じでいいかなぁ。
APIへのリクエストは非同期だから問題ないと。

ある日、うちの広告配信の導入を検討していたクライアントからご指摘をもらいました。
「Google PageSpeed Insightsで修正必須項目に引っかかっているから入れらません。」
知っていますか？
[Google PageSpeed Insights。](https://developers.google.com/speed/pagespeed/insights/?hl=ja)
サイトで表示の遅延の原因やら何やら、懇切丁寧に教えてくれるサービスです。

![PageSpeed Insights.png](https://allabout.qiita.com/files/c0b5bc1b-0d7f-9327-4832-bfb4993a2bef.png)

この項目に引っかかっていました。
おかしいぞ、なぜだ？
と、思ってたら原因はこちら。

```php:ダメだったパターン
<script type="text/javascript" src="hoge.js">　←　これ。
```

これがレンダリングをブロックすると。言われてみればそのとおりだけど。。
ちゃんとscriptタグにはこれをつけないといけません。

```php:大丈夫なパターン
<script type="text/javascript" src="hoge.js" async>　←　async。これ。
```

ただ、これをつけると元々記載していた発火の処理がそんなオブジェクト無いよってエラーになるので、
最終的に下記のような形になるように修正をしました。

```php:最終的な形
<script type="text/javascript" src="hoge.js">
</head>

～ 省略 ～

<script type="text/javascript">
// ここで処理を発火 内部で非同期に通信を行いクリエイティブを返す
new getAd();
</script>

↓

// 発火の処理もhoge.jsに纏めて、scriptタグもbody閉じタグ前に置くことを推奨する形に。
<script type="text/javascript" src="hoge.js" async>
</body>
```

地味に大変だったのですが、これで諸問題をクリアー。
技術力・知識の無さを露呈しつつも、なんとか導入もしてもらえて一安心…地味に大変だったけど。

気にしましょう、**Google PageSpeed Insights！**

## 2. XMLHttpRequest Levele2
これもjavascriptのお話です。
非同期通信と密接に関わってきますが、一言でいうとサーバーへの通信をおこなうオブジェクトです。
あまり普段は気にしないかもしれないですが、Level2からCORS（クロスドメインでのリクエスト）が可能となっています。

```php:以前はできなかった
a.com → a.com　の通信は◯
a.com → b.com　の通信は✖
```

```php:今ではできる
a.com → a.com　の通信は◯
a.com → b.com　の通信は◯

※サーバーサイドでResponseHeaderに下記の設定を返すようにしないと動きません。
Access-Control-Allow-Origin: *
```

XMLHttpRequestはそれだけではなく、通信先のサーバーからの応答が遅延しているとき、エラーが返ってきてしまったときの処理で分岐できたりもするのでとても便利です。

使い方も非常にシンプル。

```php:使い方サンプル
var request_url = "http://hoge.com/test.php";
var xhr = new XMLHttpRequest;
xhr.onload = function(){
  //リクエストの戻り値
  console.log(xhr.responseText);
},
xhr.onerror = function(){
  // エラー時の処理
},
xhr.ontimeout = function(){
  // サーバーからの応答が指定秒（ms）返って来ないときの処理
},
xhr.open("GET", request_url), // リクエスト方法とリクエスト先を指定
xhr.timeout = 1000, // リクエストが返って来ないときの分岐に入る秒数指定
xhr.send(); // リクエスト送信

```
他にも色々と設定できたりしますが、数行でサーバーへのリクエストが可能になります。
普段、Jqueryを利用している人はこの記述等がそれに該当します。

```php:sample

$.ajax({
  type: "GET",
  url: "http://hoge.com/test.php",
  data: {location:"Tokyo"}
}).done(function(response) {
  console.log(response);
});

※他に書き方もありますが、内部ではXMLHttpRequestを利用しています。
```

さて、XMLHttpRequestを導入するにあたり、大人な事情でJqueryのようなライブラリが利用できなかったので、色々な問題と直面しながらも自前で実装しました。

### 1. ブラウザ問題 その１
まず、XMLHttpRequest level2 ですが、
**IE7、Opera mini では動きません。**
ブラウザ自体が対応していないので、速やかにJSONPでのリクエスト方法に切り替えましょう。
ちなみに、XMLHttpRequest level2に対応しているブラウザかどうかの判定は、こんな形で実装しています。

```php:これで判定してます
    // ie7、もしくはwindow.XDomainRequestかwindow.XMLHttpRequestが使えないブラウザを判定
    _supportXHR2: function() {
      var a = navigator.userAgent.toLowerCase(),
          b = /(msie) ([\w.]+)/.exec(a) || [],
          c = parseInt(b[2] || 99, 10);
      return 7 >= c ? !1 : window.XDomainRequest || window.XMLHttpRequest ? !0 : !1;
    }
```

### 2. ブラウザ問題 その２
またブラウザです。
**IE8では XMLHttpRequest のオブジェクトはサポートしていません。**
代わりにこれを使います。
**XDomainRequest**
もうよくわからないですが、IE8はこれを使うことでちゃんと動作します。
ちなみに、インスタンスを指定する時に下記の判定で分岐するようにしています。

```php:これで判定
_createRequestInstance: function() {
      return window.XDomainRequest ? new XDomainRequest : new XMLHttpRequest;
}
```

### 3. ブラウザ問題 その３
もう嫌になります。
ここがハマったポイントです。
上記に上げた問題、諸々クリアーして実際にリリースしたのですが
**IE8、IE9、IE10 で動かない。**
javascriptのエラーを見てみると、

```php:こんなエラー　もう勘弁して
アクセスが拒否されました
```
こ、これだけ。
途方にくれつつも色々と調べたのですが、原因は**プロトコル**でした。

```php:このパターンだとIE8、9、10はXHR通信できません

タグを埋め込んだサイトのプロトコルがhttp → 広告を取得するリクエストがhttpsの時

ex.)
A: http://hoge.com/ → B:https://ad.com/get.php
AからBへのXHR通信の際に、プロトコルが違うとエラーが起きます。
```
**ちなみにこれは、IEの仕様です。**
のっぴきならない理由がなければ、プロトコルは合わせるようにしましょう。
ちゃんとテストすれば…とか、声が聞こえてきそうですが、またしても無能を露呈しつつも一つ勉強になったと前向きに捉えています。

早くなくならないかな、**IE。**

## 最後に

普段、何気なく利用しているものでも深掘りしてみれば知らないことばかりで、発見の日々でした。
とはいえ、まだまだ課題は山盛りなので、…でも今年はこの辺にして。
来年から本気を出そうと思います。