Rx応答プログラミング
一、Observable
Observableは文面から「観察者」と呼ばれています。つまり、ある「データソース」または「イベントソース」です。このようなデータソースは観察できる能力を持っています。これはあなたが自発的にデータを取得するのとは本質的な違いがあります。イメージの比喩を使うと、Observableは蛇口のようなものです。蛇口を開けてもいいです。Observableを購読してから、水が出てきます。これは応答式プログラミングの核心思想です。でも、これは本編の文章の中では詳しく分かりません。
Observableは、異なる方法で具体的に実現できる概念であり、本稿では高次関数によって2つのよく使われるObservable:froomEventとIntervalを実現する。Observableに対する購読と購読のキャンセルの二つの行為を解説することによって、読者がObservableとは何かを本当に理解するのを助けます。
二、高次関数
高次関数の概念は関数式プログラミングから来ています。簡単な定義は関数の入力または戻り値が関数の関数です。たとえば:
上記のfoo関数の呼び出しは、そのままハローワールドを印刷するのではなく、このハローワールドをキャッシュするだけです。後は実際の必要に応じて戻りBar関数を呼び出して、本当にハローワールドを印刷する作業を行います。
なぜこのようにパッケージ化するのですか?実際にこのようにする効果は「遅延」コールです。すべてのエッセンスはこの「遅延」の中にあります。私たちは実際に一つの行為を包装しました。まるで同じようなものです。
中には違うものを入れることができますが、物流にとっては統一されたものです。そのため、積み重ねる、運送、保管、さらに箱を開けるという動作も同じです。
前の例に戻ると、foo関数を呼び出して、宅配便の箱を梱包するのに相当します。この速達箱の中には固定的なプログラムがあります。つまり、この速達箱を開けたら、印刷操作を実行します。
foo 1、foo 2、foo 3…様々なプログラムがありますが、これらのfoosには共通の操作があります。前提としては、このfooは関数を返します。このようにすると、「開く」動作、すなわち戻りの関数を呼び出すことができます。
3.1、宅配ボックスモデル1:froomEvent
上記の基礎がありました。Rxプログラムで一番よく使われているObservable-froomEventを見に来ました。Rxプログラミングの初心者にとって、初めはフロムイベント(…)とaddEventListener(…)の違いが分かりにくいです。
froomEventは実際にaddEvent Listenerに対しての「遅延」呼び出しです。
どのようにsubscribeを実現するかについては、本明細書では議論されない範囲で、Rxプログラミングにおいて、このsubscribeの動作を「購読」といいます。購読とはすべてのObservableの統一された操作です。本文ではObservableに対する「呼び出し」は、論理的にはsubscribeに相当する。
次にもう一つの例を挙げます。基本的に読者に二反Nを挙げられます。
3.2、宅配便の箱のモデル2:interval
Rxの中にintervalがありますが、set Intervalとはどのような違いがありますか?
すでに回答が始まっている人がいると思いますが、intervalはset Intervalの遅延コールです。ビンゴ!
froomEventとInterval自体は「宅急箱」の模型を作っています。呼び出して戻ってくるものだけが「速達箱」です。froomEvent(btn、「click」)、interval(1000)など…
四、高次の速達箱
上の基礎があって、下から段階を始めます。私達はそんなに多くの宅配便の箱を持っていますので、これらの宅配便の箱を再包装してもいいです。
文章の冒頭で述べました。宅配便の箱はいくつかの操作を統一しています。だから、たくさんの宅配便の箱を積み重ねます。つまり、大きな宅配便の箱にセットします。この大きな宅配便の箱は小さい宅配便の箱と同じで、「開く」操作(つまり購読)があります。この大きな宅配ボックスを開けると、何がありますか?
小さな宅配ボックスを一つずつ開けたり、小さな宅配ボックスを一度に開けたりするなど、さまざまな可能性があります。一番開けやすい宅配ボックスだけを開けてもいいです。
以下は簡略版のmerge方法です。
二つのObservableをmerge法を使用して組み合わせます。
これは私達がどうして苦労して各種の非同期の関数を速達の箱(Observable)に包装しますか?もちろん「オン」だけです。(購読)この操作は一番初期の機能です。次からステップを開始します。
五、宅配ボックスの廃棄
5.1、宅配便の廃棄――購読をキャンセルする
私たちはやはりfroomEventを例にして、addEvent Listenerのパッケージとして簡単な高次関数を書きました。
じゃ私達はどうやってこの開けた宅配便の箱を廃棄しますか?
まず、私達はもう開けた宅配ボックスを必要とします。上の関数の呼び出し結果はvoidです。私達は何の操作もできないので、開けた状態の宅配ボックスを作る必要があります。それとも高次関数を使うかという考えです。戻り関数の中からもう一つの関数を返して、廃棄操作に使います。
私たちはmergeを例にとって:
六、補充
ここで私たちはObservableの二つの重要な操作(購読、購読取り消し)を説明しました。注意すべきなのは、購読をキャンセルする行為はObservableに作用するのではなく、すでに「開いている」宅配ボックス(Observableに購読して戻ってくるもの)の上に作用することです。
Observableには、この他にも二つの重要な操作があります。即ち、イベントを出すこと、完了すること、異常を出すことです。
この二つの行為は速達箱ではイメージが違っています。私達はObservableを蛇口に比べることができます。元々の速達箱を開けたら蛇口をひねるようになりました。私達が入ってきたコールバック関数は水を飲むコップにたとえられます。みなさんはコールバック関数についてよく知っていますので、ここではもう詳しく説明しません。
七、後記
私たちが勉強している内容をまとめてみます。高次関数を通じて、いくつかの操作を「遅延」し、統一的な行動を与えました。
これらのいわゆる「遅延」実行とは、Rxプログラミングの舞台裏が最も理解しにくく、最も核心的な部分である。Rxの本質は、非同期関数をカプセル化し、4つの行為に抽象化することである。購読、キャンセル、イベントの発行、完了/異常。
実際にRxライブラリを実現する方法はたくさんありますが、ここでは高次関数の思想を利用してObservableの本質を理解することを助けます。公式に実現されたバージョンでは、Observableという宅配便の箱は高次関数ではなく、対象ですが、本質的には同じです。
以上はRx応答式プログラミングの詳細を述べました。Rx応答式プログラミングに関する資料は他の関連記事に注目してください。
Observableは文面から「観察者」と呼ばれています。つまり、ある「データソース」または「イベントソース」です。このようなデータソースは観察できる能力を持っています。これはあなたが自発的にデータを取得するのとは本質的な違いがあります。イメージの比喩を使うと、Observableは蛇口のようなものです。蛇口を開けてもいいです。Observableを購読してから、水が出てきます。これは応答式プログラミングの核心思想です。でも、これは本編の文章の中では詳しく分かりません。
Observableは、異なる方法で具体的に実現できる概念であり、本稿では高次関数によって2つのよく使われるObservable:froomEventとIntervalを実現する。Observableに対する購読と購読のキャンセルの二つの行為を解説することによって、読者がObservableとは何かを本当に理解するのを助けます。
二、高次関数
高次関数の概念は関数式プログラミングから来ています。簡単な定義は関数の入力または戻り値が関数の関数です。たとえば:
function foo(arg){
return function(){
console.log(arg)
}
}
const bar = foo(“hello world”)
bar() // hello world
ps:高次関数ができることが多いです。ここでは本論文に必要な状況だけを使っています。上記のfoo関数の呼び出しは、そのままハローワールドを印刷するのではなく、このハローワールドをキャッシュするだけです。後は実際の必要に応じて戻りBar関数を呼び出して、本当にハローワールドを印刷する作業を行います。
なぜこのようにパッケージ化するのですか?実際にこのようにする効果は「遅延」コールです。すべてのエッセンスはこの「遅延」の中にあります。私たちは実際に一つの行為を包装しました。まるで同じようなものです。
中には違うものを入れることができますが、物流にとっては統一されたものです。そのため、積み重ねる、運送、保管、さらに箱を開けるという動作も同じです。
前の例に戻ると、foo関数を呼び出して、宅配便の箱を梱包するのに相当します。この速達箱の中には固定的なプログラムがあります。つまり、この速達箱を開けたら、印刷操作を実行します。
foo 1、foo 2、foo 3…様々なプログラムがありますが、これらのfoosには共通の操作があります。前提としては、このfooは関数を返します。このようにすると、「開く」動作、すなわち戻りの関数を呼び出すことができます。
function foo1(arg){
return function(){
console.log(arg+"?")
}
}
function foo2(arg){
return function(){
console.log(arg+"!")
}
}
const bar1 = foo1(“hello world”)
const bar2 = foo2("yes")
bar1()+bar2() // hello world? yes!
三、宅配便の模型3.1、宅配ボックスモデル1:froomEvent
上記の基礎がありました。Rxプログラムで一番よく使われているObservable-froomEventを見に来ました。Rxプログラミングの初心者にとって、初めはフロムイベント(…)とaddEventListener(…)の違いが分かりにくいです。
btn.addEventListener("click",callback)
rx.fromEvent(btn,"click").subscribe(callback)
このコードを直接実行すれば、確かに効果は同じです。違いはどこですか?最も直接的な違いは、froomEvent(…)ではなくsubscribe関数がbtnに作用し、addEventListenerが直接btnに作用することである。subscribe関数は何かの「開く」操作です。froomEvent(...)はある種類の宅配便箱です。froomEventは実際にaddEvent Listenerに対しての「遅延」呼び出しです。
function fromEvent(target,evtName){
return function(callback){
target.addEventListener(evtName,callback)
}
}
const ob = fromEvent(btn,"click")
ob(console.log)// subscribe
えっと、froomEventは本質的に高次関数である。どのようにsubscribeを実現するかについては、本明細書では議論されない範囲で、Rxプログラミングにおいて、このsubscribeの動作を「購読」といいます。購読とはすべてのObservableの統一された操作です。本文ではObservableに対する「呼び出し」は、論理的にはsubscribeに相当する。
次にもう一つの例を挙げます。基本的に読者に二反Nを挙げられます。
3.2、宅配便の箱のモデル2:interval
Rxの中にintervalがありますが、set Intervalとはどのような違いがありますか?
すでに回答が始まっている人がいると思いますが、intervalはset Intervalの遅延コールです。ビンゴ!
function interval(period){
let i = 0
return function(callback){
setInterval(period,()=>callback(i++))
}
}
const ob = interval(1000)
ob(console.log)// subscribe
上の二つの例から見て、froomEvent(…)であろうと、Intervalであろうと、内部は全く違った論理ですが、彼らは同じ「速達箱」というものに属しています。私たちはそれをObservableと呼んでいます。froomEventとInterval自体は「宅急箱」の模型を作っています。呼び出して戻ってくるものだけが「速達箱」です。froomEvent(btn、「click」)、interval(1000)など…
四、高次の速達箱
上の基礎があって、下から段階を始めます。私達はそんなに多くの宅配便の箱を持っていますので、これらの宅配便の箱を再包装してもいいです。
文章の冒頭で述べました。宅配便の箱はいくつかの操作を統一しています。だから、たくさんの宅配便の箱を積み重ねます。つまり、大きな宅配便の箱にセットします。この大きな宅配便の箱は小さい宅配便の箱と同じで、「開く」操作(つまり購読)があります。この大きな宅配ボックスを開けると、何がありますか?
小さな宅配ボックスを一つずつ開けたり、小さな宅配ボックスを一度に開けたりするなど、さまざまな可能性があります。一番開けやすい宅配ボックスだけを開けてもいいです。
以下は簡略版のmerge方法です。
function merge(...obs){
return function(callback){
obs.forEach(ob=>ob(callback)) //
}
}
前のfroomEventとintervalを例に挙げましょう。二つのObservableをmerge法を使用して組み合わせます。
const ob1 = fromEvent(btn,'click') // 1
const ob2 = interval(1000) // 2
const ob = merge(ob1,ob2) //
ob(console.log) //
私たちが「開く」(購読)という大きな宅配便箱をobすると、その中の二つの小さな宅配便箱も「開く」(購読)され、いずれかの小さな宅配便箱の中のロジックが実行され、私たちは二つのObservableを合併して一つになります。これは私達がどうして苦労して各種の非同期の関数を速達の箱(Observable)に包装しますか?もちろん「オン」だけです。(購読)この操作は一番初期の機能です。次からステップを開始します。
五、宅配ボックスの廃棄
5.1、宅配便の廃棄――購読をキャンセルする
私たちはやはりfroomEventを例にして、addEvent Listenerのパッケージとして簡単な高次関数を書きました。
function fromEvent(target,evtName){
return function(callback){
target.addEventListener(evtName,callback)
}
}
この関数を呼び出すと、私達は一つの宅配ボックス(froomEvent(btn,‘click’)を生成しました。この関数が戻ってくる関数を呼び出したとき、私たちは宅配ボックスを開けました。じゃ私達はどうやってこの開けた宅配便の箱を廃棄しますか?
まず、私達はもう開けた宅配ボックスを必要とします。上の関数の呼び出し結果はvoidです。私達は何の操作もできないので、開けた状態の宅配ボックスを作る必要があります。それとも高次関数を使うかという考えです。戻り関数の中からもう一つの関数を返して、廃棄操作に使います。
function fromEvent(target,evtName){
return function(callback){
target.addEventListener(evtName,callback)
return function(){
target.removeEventListener(evtName,callback)
}
}
}
const ob = fromEvent(btn,'click') //
const sub = ob(console.log) // ,
sub() //
同じように、インターバールに対しても、同じようにして作成することができます。
function interval(period){
let i = 0
return function(callback){
let id = setInterval(period,()=>callback(i++))
return function(){
clearInterval(id)
}
}
}
const ob = interval(1000) //
const sub = ob(console.log) //
sub() //
5.2、高次の宅配便の箱を廃棄する私たちはmergeを例にとって:
function merge(...obs){
return function(callback){
const subs = obs.map(ob=>ob(callback)) //
return function(){
subs.forEach(sub=>sub()) //
}
}
}
const ob1 = fromEvent(btn,'click') // 1
const ob2 = interval(1000) // 2
const ob = merge(ob1,ob2) //
const sub = ob(console.log) //
sub() //
私たちは大きな宅配便の箱を廃棄すると、中のすべての小包箱を一緒に廃棄します。六、補充
ここで私たちはObservableの二つの重要な操作(購読、購読取り消し)を説明しました。注意すべきなのは、購読をキャンセルする行為はObservableに作用するのではなく、すでに「開いている」宅配ボックス(Observableに購読して戻ってくるもの)の上に作用することです。
Observableには、この他にも二つの重要な操作があります。即ち、イベントを出すこと、完了すること、異常を出すことです。
この二つの行為は速達箱ではイメージが違っています。私達はObservableを蛇口に比べることができます。元々の速達箱を開けたら蛇口をひねるようになりました。私達が入ってきたコールバック関数は水を飲むコップにたとえられます。みなさんはコールバック関数についてよく知っていますので、ここではもう詳しく説明しません。
七、後記
私たちが勉強している内容をまとめてみます。高次関数を通じて、いくつかの操作を「遅延」し、統一的な行動を与えました。
これらのいわゆる「遅延」実行とは、Rxプログラミングの舞台裏が最も理解しにくく、最も核心的な部分である。Rxの本質は、非同期関数をカプセル化し、4つの行為に抽象化することである。購読、キャンセル、イベントの発行、完了/異常。
実際にRxライブラリを実現する方法はたくさんありますが、ここでは高次関数の思想を利用してObservableの本質を理解することを助けます。公式に実現されたバージョンでは、Observableという宅配便の箱は高次関数ではなく、対象ですが、本質的には同じです。
以上はRx応答式プログラミングの詳細を述べました。Rx応答式プログラミングに関する資料は他の関連記事に注目してください。