howdylikes

Google Developersってわかりづらいよね

AngularJS プロミス $q

jQueryでいう$.Deferredですかね。

https://code.angularjs.org/1.4.8/docs/api/ng/service/$q

$q.defer()でdeferredオブジェクトを取得してdeferred.promiseを返すようにする。
deferredオブジェクトにはpromiseと3つのメソッドが存在し必要に応じて使用する。

promise: Promise
resolve: (value) // 成功用
reject: (value) // 失敗用
notify: (value) // 通知用

promiseには以下の3つのメソッドが存在する。
通常はthenを使用し失敗時だけハンドリングしたい場合はcatch、結果問わず後処理をしたい場合はfinallyを使用。

then(successCallback, errorCallback, notifyCallback)
catch(errorCallback)
finally(callback, notifyCallback)

$q.all(promises);ですべてのプロミスが解決したあとに解決するプロミスを生成する

e.g.

AngularJS controller asと $watchの指定

github.com

上記のスタイルガイドに以下の様な説明があるのですが

Note: controller asを用いたコントローラの中で watch を作成したときは、次のシンタックスで vm.* のメンバを watch することができます。(digestのサイクルに追加の負荷がかかることに注意してwatchを作成します。)

これを指定しちゃうとcontroller asに指定した値で縛られちゃうので微妙な気がするんですよね。
2のパターンで書くほうが良い気がする。そこまで可読性が落ちるわけでもないですし。

GoogleAppsのカレンダーリソースに対して予定の時間枠の権限で予約が可能に

公式ブログで発表されました。

http://googleappsupdates.blogspot.jp/2016/01/book-resources-that-are-shared-as-see.html

予定の時間枠表示の権限でカレンダーリソースに対して予約ができる設定が可能になりました。
※個人で作成したカレンダーは対象外です。あくまでもカレンダーリソースです。

設定

アプリ>Google Apps>カレンダー の設定
この画面でチェックを入れます f:id:howdy39:20160113125130p:plain

予約

会議室で該当のリソースを選びます。
f:id:howdy39:20160113205817p:plain

自分で予約したのにリソースの方は予定ありで中身が見れない状態になっています。 f:id:howdy39:20160113205943p:plain

設定を元に戻したらどうなる?

この状態でチェックを戻してみましたが予約が消えるということはありませんでした。
もちろん新規で予約はできなくなります。
f:id:howdy39:20160113211625p:plain

あとがき

用途としては社内の人に知られてはいけない極秘な会議をする会議室用?とかですかね。

あんまりないと思いますが、カレンダーリソースのACLを取得して予約可(不可)等を切り替えてる場合は注意が必要です。

AngularJS 変更監視 Scope#$watchの補足とScope#$apply

$watchについて以前書きましたがその補足と$applyについてです。
blog.howdylikes.jp

文字列の代わりにfunctionで変更監視対象を直接指定することが可能

と記載しましたがその補足です。
以下のscript内ではwindowオブジェクトのglobalを監視対象としています(普通は書きませんが動作確認のためです)

this.dummy()が呼ばれた場合もScopeの監視処理自体は走ります。
※ng-clickで$digestサイクルが実行されるかららしい

changeValue()が呼ばれた場合、globalを書き換えても$digestサイクルが実行されないのでScopeの監視処理は走りません。

callApply()内で$scopeを取得して$apply()を実行していますが、これは内部的に$digestサイクルを実行しているということらしい。

つまりchangeValue()の後にthis.dummy()callApply()など$digestサイクルが実行されるような処理を行えばthis.clickと同じような動きになる。

var global = 'hello, world';

angular.module('myapp', [])
    .controller('myController', function ($rootScope, $scope) {
        $rootScope.$watch(
            function () {
                console.log('監視処理が動く');
                return global
            }, function (newValue, oldValue, scope) {
                console.log('globalが変更されました:' + newValue) ;
            });

        this.click = function() {
            console.log('this.click');
            global = new Date();
        }
        this.dummy = function() {
            console.log('this.dummy');
        }
    });

function changeValue() {
    console.log('changeValue');
    global  = new Date();
}

function callApply() {
    console.log('callApply');
    angular.element('#myCtrl').scope().$apply();
}

まとめ

$watchは監視処理を定義する
$digestサイクル内で監視処理を呼ぶ($rootScopeから先に呼ばれていたことから察すると$rootScope(親Scope)が優先順位が高いと思われる)
ng-clickなど$digestサイクルを呼ぶ処理がある(入力値を変えた時とかもおそらく呼ばれている=これがAngularのデータバインディングの正体か)

今年買ったガジェット(電化製品)

5段階評価でいきます。 星3は普通、星4は満足、星5は壊れたら同じor上位品を買う。

Colorio PX-047A

プリンタです、確定申告と請求書等に使ってます。
省スペースなのがGood。スキャナーもついてますし、無線で印刷できるし機能は十分です。
★★★☆☆

YOTAPHONE 2

ロシアメーカーのシムフリースマホ。
背面が電子ペーパーになっているのが最大の特徴です。
電子書籍として使うには小さすぎるので実際は時計代わりとデザイン的な意味合いでしょうね。
Yotaタブレットのがほしいです(9〜11インチぐらいで)。
端末自体は満足していますがちょっと高いので3がでても多分買わない。
★★★★☆

PHILIPS(フィリップス) 電動歯ブラシ ソニッケアー ダイヤモンドクリーン ブラック HX9313/54

電動歯ブラシです。
無接点充電のコップが付いてるのが特徴ですね。 コップに入れるだけなのでこれは便利。

ブラウン→PHILIPS→ドルツ→PHILIPSときました。。
ドルツは機能的には糞です。ただ維持費は安いです。。
PHILIPSはその逆です。
★★★★☆

iRobot ブラーバ380j

お掃除ロボット。
付属の濡れ吹きと市販のクイックルワイパー系が使えます。
100均で枚数の少ない分厚いやつのウェットタイプを主に使ってます。
生活スタイルがガラリと変わりました。 ほぼ毎日稼働してます。

以前ルンバもどきを使っていましたがゴミを捨てるのが嫌なんですよね。
ブラーバはクイックルワイパーをつける、はずすだけなので楽チンです。
★★★★★

ネスカフェ ドルチェグスト ワインレッド ジェニオプレミアム

コーヒーマシンです。
缶コーヒーとか不味くて飲めない。
ドリップコーヒーはめんどくさい。
という方にピッタリだと思います。
★★★★★

パナソニック 3つ星 ビストロ スチームオーブンレンジ 26L ブラウン NE-BS651-T

電子レンジ。
揚げ物とか温めるときにサクッとできるんですが水入れなければいけなくて面倒です。
★★★☆☆

APPLE MacBook (1.2GHzデュアルコア Intel CoreMプロセッサ/12型/8GB/512GB/USB-C/スペースグレイ) MJY42J/A

MacBook Pro から買い替え。
軽くてそれなりスペック。
Web開発ぐらいだったら十分かと。(動画編集とかスマホアプリとかはしんどいかと)
毎日会社に持って行ってます。
★★★★★★

ソニー 地上・BS・110度CSデジタルハイビジョン液晶テレビ BRAVIA X8500C 49V型 KJ-49X8500C

4K Android TVです。
キャストで事足りるのでAndroid TV本来の機能を使うことはないと思います。 (地デジもレコーダーのディスプレイとして使っているだけ) デザインや画質など好きなTVを買ってChrome Castを挿すことを勧めます。

まだ使って間もないので未評価

総評

今年はあんま買わなかったと感じていたのですがまとめてみると意外と買ってましたね。

日常的に使う物の価値は運用が楽かどうかが重要だと思います。

ブラーバは交換が楽。ドルチェグストは作るのも片付けも楽。 MacBookは軽いので持ち運びが楽。
ビストロは片付けがめんどくさいからスチームオーブンは使わない。 Android TVもスマホからキャストしたほうが楽だから使わない。

どれだけ優れた機能も面倒だと使いませんよね。 その辺を重視して買物をすると満足できる結果になりそうです。

AngularJS 変更監視 Scope#$watch、 Scope#$watchGroup、Scope#$watchCollection

リファレンス
https://code.angularjs.org/1.4.7/docs/api/ng/type/$rootScope.Scope#$watch

$watch

1つのプロパティを監視する
$watch(watchExpression, listener, [objectEquality]);
objectEqualityをtrueで指定するとangular.equalsを使用する

angular.module('myapp', [])
    .run(function() {
        console.log("myapp.run");
    })
    .controller('myController', function ($scope) {

        // $watch
        $scope.message = 'Hello, World!';
        $scope.$watch('message', function (newValue, oldValue, scope) {
            console.log('$scope.$watch(message)', newValue, oldValue);
        });
    });
}
// console
myapp.run
$scope.$watch(message) Hello, World! Hello, World!

変更をしなくても初期状態の設定だけで呼ばれる模様、ただしrunの後。

$watchGroup

複数のプロパティを監視する
$watchGroup(watchExpressions, listener);
いずれかが変わったら指定されたfunctionが呼ばれる感じ。

        // $watchGroup
        $scope.$watchGroup([
            'message',
            'message2'
        ], function (newValue, oldValue, scope) {
            console.log('$scope.$watchGroup([message])');
        });

$watchCollection

配列やオブジェクトを監視する用?
$watchCollection(obj, listener);
1階層だけ変更を監視します。
配列なら配列の要素の追加や削除は引っかかるがプロパティの変更は引っかからない。
オブジェクトならプロパティの変更が引っかかる。

        // $watchCollection (対象が配列)
        $scope.messages = [{"message":"hoge1"}, {"message":"hoge2"}];
        $scope.$watchCollection('messages', function (newValue, oldValue, scope) {
            console.log('$scope.$watchCollection(messages)');
        });

        this.pushMessage = function() {
            $scope.messages.push({"message":"hogex"}); // ひっかかる
        }
        this.popMessage = function() {
            $scope.messages.pop();  // ひっかかる
        }
        this.changePropertyMessage = function() {
            $scope.messages[$scope.messages.length-1].message = 'change';  // ひっかからない
        }

        // $watchCollection (対象がオブジェクト)
        $scope.messageinfo = {type: 'type'};
        this.messageinfo = {type: 'typo'};

        $scope.$watchCollection('messageinfo', function (newValue, oldValue, scope) {
            console.log('$scope.$watchCollection(messageinfo)'); // ひっかかる
        });

その他

上記例では変更監視対象を文字列で指定していました。
この場合$scopeの文字列のプロパティを監視するということです。

また、文字列の代わりにfunctionで変更監視対象を直接指定することが可能です。
その場合$scopeに深い意味はないです。監視対象にするための機能を呼び出しているようなものでしょうか。
そのため$rootScopeで対象オブジェクトを渡しても動作します。
これを使えばController asを使っている場合に$scopeをControllerから排除できそうです。

以下のプログラムは何が表示されるでしょうか。

angular.module('myapp', [])
    .run(function() {
        console.log("myapp.run");
    })
    .controller('myController', function ($scope, $rootScope) {

        var self = this;
        this.message = 'Hello, World!';
        $scope.$watch(
            'message', function (newValue, oldValue, scope) {
                console.log('これは呼ばれる?1');
            });
        $rootScope.$watch(
            'notDefinition', function (newValue, oldValue, scope) {
                console.log('これは呼ばれる?2');
            });
        $rootScope.$watch(
            function () {
                return self.message;
            }, function (newValue, oldValue, scope) {
                console.log('これは呼ばれる?3');
                $scope.message = '$scope.message' + new Date();
            });

        this.click = function() {
            this.message = 'hoge' + new Date();
        }
    });
// console
myapp.run
これは呼ばれる?2
これは呼ばれる?3
これは呼ばれる?1

// this.clickを呼ぶ
これは呼ばれる?3
これは呼ばれる?1

どうも定義順ではなく$rootScopeから(親Scopeから?)呼ばれるようです。
またそもそもプロパティが未定義でも最初に呼ばれるというのはちょっと不思議な感じがしますが
$watchは定義時と変更時に呼ばれると覚えれば良さそうです。

また指定したプロパティを監視する定義をしているだけでrun終了時にプロパティが存在していなくても問題なく、見に行ったけどundefinedだったと記憶しているようなイメージです。
そのためoldValueもnewValueもundefined→変わっていない。
上記で言うとscope.message = '$scope.message' + new Date(); でプロパティを設定した段階でoldValueがundefinedでnewValueに文字列が設定された→変わった。という判断をしているのでしょう。。多分。