ラベル JavaScript の投稿を表示しています。 すべての投稿を表示
ラベル JavaScript の投稿を表示しています。 すべての投稿を表示

2013年11月2日土曜日

[Angular.js]factoryとserviceの使い分けについて

最近、プライベートのプロダクトでAngular.jsを勉強がてら使っている。
Yeomanでgenerator-angularを使う方法でやってたり。
で、結構悩んで調べたことがあったので、メモ。
※使い始めて間もないので、間違いがあったらご指摘ください。

サービスを作るやり方、Angular.jsだと色々あります。
yeoman-generatorのREADMEを参考に挙げると

service, factory, provider, value, constant
と、実にたくさん。

providerとvalueとconstantは、名前からなんとなく使い分けが判るんだけど、
serviceとfactoryの違いって何よ?って結構悩んだ。
簡単な実装例だと、「結局どっちも書き方が違うだけで同じ事してるやん」って思ってしまって…。

悩んだ時はソース嫁、という事で読んで見ました。
実装はこのへん。

factoryは、渡したfunctionをfunctionのままサービスに登録する。
serviceは、渡したfunctionをコンストラクタとしてインスタンスを生成し、そのインスタンスをサービスに登録する。

という違いがある様子。

それで何が変わるのか?というと。

serviceはインスタンスにしてから登録する。
JavaScriptのオブジェクトにはprivateが無いので、serviceで登録したコンストラクタで定義したメソッドは、何処からでも参照する事が出来てしまう。

一方、factoryはfunctionをそのまま登録する。
そして、factoryで登録したサービスから見えるのは、function内でreturnしたオブジェクトだけ。
なので、以下のように書いておくと、privateのような事が出来る。
angular.module('sampleServices', []).
    factory('nyanService', function() {
        var privateValue = 0;
        var privateMethod = function() {
            privateValue++;
        };
        return {
            publicMethod: function() {
                privateMethod();
                return privateValue();
            }
        };
    });
テストはこんな感じのが通る。
  describe('factory tests', function() {
      it('publicMethodがサービス経由で見えること', function() {
          expect(nyanService.publicMethod).toBeDefined();
      });
      it('privateMethodがサービス経由で見えないこと', function() {
          expect(nyanService.privateMethod).toBeUndefined();
      });
      it('privateValueがサービス経由で見えないこと', function() {
          expect(nyanService.privateValue).toBeUndefined();
      });
      it('1回実行すると1が帰ってくること', function() {
          expect(nyanService.publicMethod()).toBe(1);
      });
      it('2回実行すると2が帰ってくること', function() {
          nyanService.publicMethod();
          expect(nyanService.publicMethod()).toBe(2);
      });
  });
なので、使い分けとしては
  • service: ある程度まとまった関数群をまとめたUtilオブジェクト向け
  • factory: ビジネスロジックをしっかり書いたりするようなモデル向け
という感じでいいんじゃないかと。

Yeomanが作ってくれるfactoryのコードにも
return{}の前に"Public API here"ってコメント書いてあるし、この使い分けで間違いない…かな?

2012年7月18日水曜日

JavaScriptのDateオブジェクトの挙動

ハマりメモ。

Dateをnewするときに渡す日付の書式でハマってしまった。

再現コード。
以下すべて、各ブラウザの開発ツールのコンソール上で実行。

Chrome 20.0.1132.57 m

new Date('2012/01/01 00:00:00');
Sun Jan 01 2012 00:00:00 GMT+0900 (東京 (標準時))
new Date('2012-01-01 00:00:00');
Sun Jan 01 2012 00:00:00 GMT+0900 (東京 (標準時))

FireFox 12.0

>>> new Date('2012/01/01 00:00:00');
Date {Sun Jan 01 2012 00:00:00 GMT+0900}
>>> new Date('2012-01-01 00:00:00');
Date {Invalid Date}

Safari 5.1.7

new Date('2012/01/01 00:00:00');
Sun Jan 01 2012 00:00:00 GMT+0900 (“Œ‹ž (•W€Žž))
new Date('2012-01-01 00:00:00');
Invalid Date


InternetExplorer 9

>> new Date('2012/01/01 00:00:00'); 
Sun Jan 1 00:00:00 UTC+0900 2012
>> new Date('2012-01-01 00:00:00');
Invalid Date



とある、JSライブラリを使ったちょっと凝った見た目の画面にて、
Chrome以外のブラウザで正常に表示できないという不具合が発生。

原因は、ライブラリに受け渡すXMLデータ上で、日付のフォーマットが
ハイフン区切りになっていたこと。
MySQLを扱ってる人には見なれたフォーマットですね。
JavaScript的には、スラッシュ区切りが正解なので、
うっかりそのまま出力した僕のミスです。

ただ、人の作ったライブラリ&日付の解釈が問題になるのがかなり奥の方のコードだったので
原因に気づくまで相当時間をかけてしまった…。

あと、「Chromeで見れればほかのブラウザでも見れるだろう」なんて安易な考えをしたのも間違い。
普段なら4ブラウザで確認はとるんだけど、
このライブラリの稼働実績がすでにあったので、
1つのブラウザで表示できれば問題ないと思ってしまった。

確認、大事。

ちなみに、Chromeはこんな書式でも正常に解釈したりする。


new Date('2012-01/01 00:00:00');
Sun Jan 01 2012 00:00:00 GMT+0900 (東京 (標準時))

日付の区切りは、-か/であればよい、という判断なのかな…?

2011年10月12日水曜日

Access-Control-Allow-Origin

 ひっさびさにjQueryを使ってajaxであれこれやってたら、
 他サイトAPIはたたけても、自作したテスト用のサイトのJSONが取得できないという謎に躓いたので、メモ。

 ドメインが異なっている場合、表題のヘッダ(Access-Control-Allow-Origin)を設定していないと、データを読むことが出来ない。
 特定のサイトからのみ読み込みOKとする場合、サイトのアドレスを、全サイトからアクセスOKとする場合、*を指定する。
 とりあえずPHPだったので、以下の1文を追加して、解決。

header("Access-Control-Allow-Origin:https://**********.jp");

 さて、上記ヘッダが正しく設定されていない場合、JSON出力側のサイト(サーバ)はどうなるのかというと
 これ、ヘッダを見て、JSON取得側が表示を拒否っているだけなので、出力側の処理は正常終了扱いになっています。
 PHP等々が動いていて、サーバ上でデータの処理やメール送信を行っている場合、そこまでは正常に動くわけです。
 ブラウザからURLを直でたたいても、正常出力されちゃうわけです。

 ブラウザのエラー出力をしっかり読めばすぐわかる話なのですが(苦笑)結構解決に時間がかかったので、メモ代わりに載せときます。