JSのPromiseとJQueryPromiseを雰囲気で理解した

雰囲気で理解したのでメモです。

JSの世界だとPromiseがあって、基本的に失敗/成功で処理を切り分けていく事ができる。 よく使われる方法だと、非同期処理を同期的に使いたいときに使われる。 例えばAというエンドポイントにアクセスした後に取得した情報で、Bエンドポイントにアクセスする必要がある場合、何も考えずにjsで書いてしまうとAの処理が終わる前にBにアクセスに行く可能性がある。

Promiseを使うとAが終わるまでBが処理されないので同期的に使うことが可能。

ちなみにJQueryの世界にはJQuery Promiseというものがある。JSのnativeなPromiseとの使い分けはこのStackOverflowが詳しい。

stackoverflow.com

要約するとPromiseサポートしていないブラウザでPromise使いたい場合はJQueryPromiseを使おうという世界観。 JQuery使っていないけど昔のブラウザでもPromise使いたいんじゃというときはcore-jsなどを使うとよしなに変換してくれるらしい。

ネイティブのPromiseだと最近はもうasync functionの内部処理か、複数一気動かすみたいなときにPromise.allを打つくらしか手で実行することはない気がする。 反面JQueryPromiseを使う場合、async functionに対応していないブラウザで動かすのが目標にある場合があるので、async functionみたいなリッチな構文を使わずに気合でPromiseを処理する必要がある。

JQueryPromiseを使う場合はDefferedオブジェクトのAPIを利用することになる。 ちょっとわかり付いらいのだけど、Promiseのresolve/rejectはPromiseに生えていそうなのだけど違っていて、Promiseオブジェクトを作ることができるDefferedオブジェクト側のAPIとして定義されている。 Defferedオブジェクトのresolve/rejectを実行することで、ネイティブのresolve/reject処理を実現している世界観。

対してPromiseがresolve/rejectした場合に処理を分岐させる、ネイティブのthenとerror処理に相当するのは、Promiseオブジェクトのthenとfailを呼ぶことで実現している。 分岐させたい処理を発生させる関数がJQueryPromiseを返すので、ネイティブのPromiseチェーンのような書き心地で書く事ができる。 わかりやすいのだとJQuery.ajaxはJQueryPromiseを返すのでそこで分岐させることが可能。

JQueryPromiseがRejectedになった場合、fail処理を受け持つのは、ネイティブのPromiseと同様に一番近いRejectハンドリング部分が受け取る。 ネイティブのPromiseの場合はcatchが受け取っていたが、JQueryPromiseの場合はfailが相当する。resolve/rejectどっちでも処理を継続させたい場合はalwaysを指定する。

const defer = $.Deferred();

ちなみにTypeScriptを使っているケースで、resolve時に値を返したい場合は、返り値の型を<>の中に指定する。

const defer = $.Deferred<HTMLHtmlElement>();

テストを書くときに強制的にPromiseをrejectしたい!!!と言うときはどうするかというと、強制的に$.Deferred().reject()を呼び出すとrejectされる。 当然resolveを強制させたいときも$.Deferred().resolve()するとよい。

例えば、sinonを使ってmockしたメソッドが返すJQueryPromiseをrejectした状態にするには次のように書く。

const stubFunction = sinon.stub(object, 'stubFunction');
stubFunction.returns($.Deferred().reject());

こうするとstubFunctionrejectされた際の挙動を取るので、例えばエラーメッセージの内容を検証したい場合は次のように続けられる。 この例ではrejectされたらfailに処理が落ちるので、errorにエラーメッセージが代入されて検証可能になる。

let error : any;
const expectError = new Error("エラー");

object.stubFunction().fail((_error) => {
   error = _error;
});

assert.equal(error.message, expectError.message, 'rejectするとエラーが帰ってくる');

こうみるとJQueryでPromiseをするには$.Deferred()を取り回せばええやんという感じになる。 とはいえぐぐると出てくるJSのPromiseの使い方とは別なので慣れるまでは大変そう。。。

参考

jsprimer.net

azu.github.io

developer.mozilla.org

perlのmapは2引数渡せる

というわけで驚きの事実です。この2行は同じhashrefを返します。

my $hoge = [map { id => $_, piyo => "bar" }, @hoge];
my $hoge = [map { {id => $_, piyo => "bar"} } @hoge];

これはmapの後ろの{はmapの開始地点の意味と、hashrefのコンストラクタとしての意味の{があります。 通常のmapの使い方だと、{をそれぞれの意味で解釈できるように2つ置く必要があります。

my $hoge = [map { {id => $_, piyo => "bar"} } @hoge];

これとは逆に{1つだとmapのhashrefのコンストラクタという意味になり、後ろにLISTが必要となります。 ドキュメントを見るとこうあります。

map BLOCK LIST
map EXPR,LIST

perldoc.jp

というわけでこうかくとhashrefがなんと手に入ります。,がポイント。

my $hoge = [map { id => $_, piyo => "bar" }, @hoge];

とはいえこの書き方はperltidyがフォーマットしてくれないのでやめたほうが良いでしょう。2引数は渡さないのが良さそう。

M1 macにGoogle日本語入力入れた

最近M1 mac使っていて、IMEmacOS標準の日本語入力を使っている。*1

標準搭載されているだけあって別に問題はないのだけれど、個人的に顔文字をIMEで出力したい。 例えば「ぶわっ」で変換したら「(`;ω;´)」が出てほしい。

辞書登録する手もあるけれど、使い慣れていたGoogle日本語入力のインストールを試した。 Google日本語入力自体はx86バージョンしか出ていないので、そのままでは動かないが、Rosetta2さえいれておけば普通にインストールできる。 30分くらい使っているけれど今の所問題はない。

とはいえ以前x86アーキテクチャmacで使っていたときは、変換候補の履歴を消すたびにIMEがフリーズするみたいな状態になったので、今回はどうなるかは微妙な気持ちになっている。ネイティブ対応のいいIMEがあったらそっちに切り替えたい。ATOK?

*1:ことえりを使っているって当初書いたけどことえりではすでにないらしい

プログラミング言語Raku(旧:Perl6)のオンリーカンファレンスが開催されるらしい

インターネット見ていたら発見してしまったのですが、ついにプログラミング言語Raku(旧 Perl6)のオンリーカンファレンスが開催されるようです。

conf.raku.org

今までのRakuはPerlのカンファレンスであるYAPCやPerlConでPerl5とセットで話される機会がほとんどでしたが、ついに初めて単独カンファレンスとなります。 今のところはトークはLTしか応募されていないようですので、みなさん応募しましょう!!(??)

Online, August 7, 2021

とのことです。 以前のThe Perl and Raku Conference 2020 cloudの際はEDTでスケジュールされていたので、日本からリアルタイムでみる場合は夜になるかと思います。


参加チケットは無料ですが、個人で寄付をすることが可能です。

面白いのはTシャツを発送することができないので、Tシャツの素材が配布されており、各自でプリントアウトしてくれ!!!という新スタイルで運用しています。僕もTシャツほしい。

f:id:anatofuz:20210516191406p:plain

ちなみに The Perl and Raku Conference 2021 cloudもやるっぽい。

w3schoolsのjQueryの練習問題解いた

jQuery全然知らないのでちょっと触ってみようと思っていた。 webサイトエイヤで構築するのも良さそうだったけど、軽い練習問題みたいなのをとりあえずガンガン進めてみたかったので、適当にググって出てきたサイトの問題を解いた

w3schoolsのチュートリアルの問題なので、まずはチュートリアルを上から眺めた。 eventの種類とか完全にわかっていなかったので、なるほどねと言いながらみていた。 jsなので自分のブラウザでも動くし、ワンクリックでどうこう動いて体験がいい。 www.w3schools.com

問題自体は穴埋め形式なので、問題文とサンプルコードを見て当てはめていく感じ。

www.w3schools.com

実際に解いた(問題として提供されていた)のは次のもの

  • Selectors
  • Events
  • Hide and Show
  • Fade
  • Slide
  • Animate
  • Stop
  • Get
  • Set
  • Add
  • Remove
  • CSS Classes
  • CSS
  • Dimensions

Ajaxチュートリアルにはあったのだけど問題にはなかったのでペラHTML作って練習するかーみたいな感じ。 jQuery完全に理解した!というわけではないのだけど、コードを読めるレベルの知見はある程度出たかなという気がする。 次は軽くなんか例題を書いて動かしてみる予定。

git commitしたら別のブランチに自動でcherry-pickするPerlスクリプトかいた

今は開発環境でM1 macを使っているのだけれど、色々あってプルリクを送りたいブランチと自分の手元のブランチが異なっているケースがある。ようはM1専用のcommitを積んでいるが、これをプルリクに含めたくないケース。

最近はgit慣れてないのもあって、commitする度にcheckoutしてcherry-pickしていたのだけど、めんどうなのでスクリプトを書いた。 自分が今作業しているブランチをhoge_m1という命名規則にして、プルリクを出すブランチをhogeにするみたいな運用。suffixで分類する。

#!/usr/bin/env perl
use strict;
use warnings;

my $git_branches = `git branch`;

die "$git_branches\n" if ($git_branches =~ /fatal: not/);

my $current_git_branch = `git branch --show-current`;
chomp $current_git_branch;

my $target_branch;
if ($current_git_branch =~ /(.*)_m1$/) {
    $target_branch = $1;
    die "not found $target_branch branch" unless ($git_branches =~ /$target_branch/);
}

system("git","commit");

system("git", "checkout", $target_branch);
system("git", "cherry-pick", $current_git_branch);

system("git", "checkout", $target_branch);

オチ

git rebase勉強した方が早かった気がする