RxJS'de boru ne için


104

Sanırım temel kavramım var, ancak bazı belirsizlikler var

Yani genel olarak gözlemlenebilir olanı böyle kullanıyorum:

observable.subscribe(x => {

})

Verileri filtrelemek istersem bunu kullanabilirim:

import { first, last, map, reduce, find, skipWhile } from 'rxjs/operators';
observable.pipe(
    map(x => {return x}),
    first()
    ).subscribe(x => {

})

Bunu da yapabilirim:

import 'rxjs/add/operator/map';
import 'rxjs/add/operator/first';

observable.map(x => {return x}).first().subscribe(x => {

})

Yani sorularım:

  1. Fark ne?
  2. Bir fark yoksa, neden boru işlevi var?
  3. Neden bu işlevler farklı ithalata ihtiyaç duyuyor?

1
Bunun özel, yerel olmayan operatörler için olduğunu söylemek üzereydim, ama bunun doğru olup olmadığını bile bilmiyorum. Oluşturduğunuz pipe()operatörleri geçmenize izin veriyor mu ?
zero298

Yanıtlar:


69

"Pipable" (eski "serbest bırakılabilir") operatörleri, RxJS 5.5'ten beri operatörleri kullanmanın mevcut ve önerilen yoludur .

Resmi belgeleri https://rxjs.dev/guide/v6/pipeable-operators okumanızı şiddetle tavsiye ederim.

Temel fark, özel operatörler yapmanın daha kolay olması ve Observableiki farklı tarafın aynı isimde bir operatör oluşturmak istediği takdirde olası çarpışmalara neden olabilecek bazı genel nesneyi değiştirmeden daha iyi anlaşılabilir olmasıdır .

importHer operatör için ayrı ifade kullanmak 'rxjs/add/operator/first', daha küçük uygulama paketleri oluşturmanın bir yoluydu. Tüm RxJS kitaplığı yerine yalnızca ihtiyacınız olan operatörleri içe aktararak toplam paket boyutunu önemli ölçüde azaltabilirsiniz. Bununla birlikte, derleyici içeri aktardığınızı bilemez 'rxjs/add/operator/first'çünkü kodunuza gerçekten ihtiyacınız vardır veya kodunuzu yeniden düzenlerken kaldırmayı unuttunuz. Bu, kullanılmayan ithalatların otomatik olarak göz ardı edildiği borulabilir operatörleri kullanmanın avantajlarından biridir.


1
Onayınız hakkında unused imports are ignored automatically, şu anda IDE'lerin kullanılmayan içe aktarmaları kaldıran eklentileri var.
silvanasono

Herkes bu IDE'leri veya bu eklentileri kullanmıyor, birçok kişi temel metin düzenleyiciyi kullanıyor. Muhtemelen çoğu zaman takımdaki herkesin bizimle aynı IDE / eklenti seti / metin düzenleyicisini kullandığını söyleyemeyiz.
Adam Faryna

3
@AdamFaryna elbette, bazı takımlar kağıda da kod yazabilir, ancak modern araçları varsa neden yapsınlar? Özellikle önemli eklentiler olmadan bir metin düzenleyici kullanmak, kağıda kod yazmaya benzer. Bunu yapabilirsiniz ama niye herhangi bir düzgün takım / geliştirici bunu yapsın
Denes Papp

@DenesPapp kod editörü, insanlar onu verimli bir şekilde kullanabildiği sürece önemli değil. Bunun dışında sadece kişisel tercihler. Kağıda kod yazma benzetmeniz yanlıştır, kağıt üzerinde kod çalıştıramazsınız ancak herhangi bir metin düzenleyicide yazılan kod çalıştırılabilir.
Adam Faryna

1
Yüklemek var ama Şunları yapabilirsiniz @perymimon rxjs-compatpaket github.com/ReactiveX/rxjs/blob/master/docs_app/content/guide/v6/...
martin

16

Boru yöntemi

Orijinal Dokümantasyona göre

borulabilir operatör, işlevin gözlemlenebilirleri girdi olarak alması ve başka bir gözlemlenebilir. önceki gözlemlenebilir kalmaları değiştirilmemiş olarak döndürmesidir.

pipe(...fns: UnaryFunction<any, any>[]): UnaryFunction<any, any>

Orijinal Gönderi

Pipo ne demek?

Bu, daha önce gözlemlenebilir örneğinde kullandığınız tüm operatörlerin, altında saf işlevler olarak mevcut olduğu anlamına gelir rxjs/operators. Bu, operatörlerden oluşan bir kompozisyon oluşturmayı veya operatörleri yeniden kullanmayı gerçekten kolaylaştırır, özel bir gözlemlenebilir genişletme Gözlemlenebilir oluşturup ardından asansörün üzerine yazarak kendi özel işinizi yapmak zorunda olduğunuz her türlü programlama jimnastiğine başvurmak zorunda kalmadan gerçekten kolay hale gelir.

const { Observable } = require('rxjs/Rx')
const { filter, map, reduce,  } = require('rxjs/operators')
const { pipe } = require('rxjs/Rx')

const filterOutWithEvens = filter(x => x % 2)
const doubleByValue = x => map(value => value * x);
const sumValue = reduce((acc, next) => acc + next, 0);
const source$ = Observable.range(0, 10)

source$.pipe(
  filterOutWithEvens, 
  doubleByValue(2), 
  sumValue)
  .subscribe(console.log); // 50

@VladKuts kodları değiştirir ve rahatsızlıktan dolayı özür.
Chanaka Weerasinghe

Teşekkürler, aktarılabilir operatörleri işlev referansları olarak saklayabileceğimi ve bunları boru () çağrısında kullanabileceğimi bile bilmiyordum. Bu, her zaman satır içi yapmaktan çok daha temiz.
Alex. A

9

Bulduğum iyi bir özet:

Akış işlemlerini (eşleme, filtreleme, azaltma ...) temel işlevlerden (abone olma, kanal oluşturma) ayırır. Zincirleme yerine borulama işlemleri yaparak, Observable'ın prototipini kirletmez ve ağaç sallamayı kolaylaştırır.

Bkz. Https://github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md#why

Nokta zincirleme için yamalı operatörlerle ilgili sorunlar şunlardır:

Bir yama işlecini içe aktaran herhangi bir kitaplık, Observable.prototype'ı bu kitaplığın tüm tüketicileri için artırarak kör bağımlılıklar oluşturacaktır. Kütüphane bunların kullanımını kaldırırsa, farkında olmadan diğer herkesi bozarlar. Boru bağlantılarında, ihtiyaç duyduğunuz operatörleri kullandığınız her dosyaya aktarmanız gerekir.

Doğrudan prototipe eklenen operatörler, toplama veya web paketi gibi araçlar tarafından "ağaç sallanamaz" değildir. Boruya bağlanabilir operatörler, doğrudan modüllerden alınan işlevler gibi olacaktır.

Uygulamalarda içe aktarılan kullanılmayan operatörler, herhangi bir yapı aracı veya tüy bırakma kuralı tarafından güvenilir bir şekilde tespit edilemez. Bu, taramayı içe aktarabileceğiniz, ancak kullanmayı bırakabileceğiniz ve hala çıktı paketinize ekleneceği anlamına gelir. Değiştirilebilir operatörlerle, kullanmıyorsanız, bir tüy bırakma kuralı sizin için onu alabilir.

Fonksiyonel kompozisyon harika. Kendi özel operatörlerinizi oluşturmak çok, çok daha kolay hale geldi ve şimdi onlar da çalışıyor ve rxjs'deki diğer tüm operatörler gibi görünüyor. Artık Observable'ı uzatmanıza veya kaldırmayı geçersiz kılmanıza gerek yok.


8

Fark ne? Örneğinizde gördüğünüz gibi, temel fark kaynak kodun okunabilirliğini artırmaktır. Örneğinizde yalnızca iki işlev var, ancak bir düzine işlev olup olmadığını düşünün. o zaman şöyle gidecek

function1().function2().function3().function4()

Gerçekten çirkinleşiyor ve okumak zor oluyor, özellikle fonksiyonların içini doldururken. Bunun da ötesinde, Visual Studio kodu gibi belirli düzenleyiciler 140'tan fazla satır uzunluğuna izin vermez. ama takip etmek gibi giderse.

Observable.pipe(
function1(),
function2(),
function3(),
function4()
)

Bu, okunabilirliği büyük ölçüde artırır.

Fark yoksa, neden borusu işlev var? PIPE () işlevinin amacı, alan ve gözlemlenebilir olan tüm işlevleri bir araya toplamaktır. Başlangıçta bir gözlemlenebilirlik alır, daha sonra bu gözlemlenebilir, onun içinde kullanılan her fonksiyon tarafından pipe () fonksiyonu boyunca kullanılır.

İlk fonksiyon gözlemlenebilir olanı alır, işler, değerini değiştirir ve bir sonraki fonksiyona geçer, ardından bir sonraki fonksiyon ilk fonksiyonun gözlemlenebilir çıktısını alır, işler ve bir sonraki fonksiyona geçer, sonra tüm fonksiyonlara kadar devam eder. pipe () işlevinin içi gözlemlenebilir olanı kullanın, sonunda işlenmiş gözlemlenebilirliğe sahip olursunuz. Sonunda, değeri çıkarmak için gözlemlenebilir olanı subscribe () işlevi ile çalıştırabilirsiniz. Unutmayın, orijinal gözlemlenebilirdeki değerler değişmez. !! 

Neden bu işlevler farklı ithalata ihtiyaç duyuyor? İçe aktarma, işlevin rxjs paketinde nerede belirtildiğine bağlıdır. Bu böyle devam ediyor. Tüm modüller, Angular'daki node_modules klasöründe saklanır. {class} öğesini "modül" den içe aktar;

Aşağıdaki kodu örnek olarak alalım. Bunu stackblitz'e yazdım. Böylece hiçbir şey otomatik olarak oluşturulmaz veya başka bir yerden kopyalanmaz. Gidip okuyabileceğiniz zaman rxjs belgelerinde belirtilenleri kopyalamanın anlamını görmüyorum. Bu soruyu burada sorduğunuzu varsayıyorum, çünkü belgeleri anlamadınız. 

  • İlgili modüllerden içe aktarılan harita, gözlemlenebilir boru sınıfları vardır. 
  • Sınıfın gövdesinde, kodda görüldüğü gibi Pipe () işlevini kullandım. 
  • Of () işlevi, abone olduğunda sırayla sayılar yayınlayan bir gözlemlenebilir döndürür.

  • Observable henüz abone değil.

  • Bunu kullandığınızda Observable.pipe () gibi, pipe () işlevi verilen Observable'ı girdi olarak kullanır.

  • İlk işlev olan map () işlevi, Gözlemlenebilir, işleyin, işlenen Gözlemlenebilir'i pipe () işlevine geri döndürür

  • daha sonra işlenen Gözlemlenebilir, varsa sonraki işleve verilir,

  • ve tüm işlevler Gözlemlenebilir'i işleyene kadar böyle devam eder,

  • sonunda Observable, pipe () işlevi tarafından bir değişkene döndürülür, aşağıdaki örnekte gözlemlenir.

Şimdi Observable'daki şey şudur: Gözlemci abone olmadığı sürece herhangi bir değer yaymaz. Bu yüzden bu Observable'a abone olmak için subscribe () işlevini kullandım, ardından abone olur olmaz abone oldum. Of () işlevi değerleri yaymaya başlar, ardından pipe () işlevi aracılığıyla işlenir ve sonunda nihai sonucu alırsınız, örneğin () işlevinden 1 alınır, map () işlevine 1 eklenir, ve geri döndü. Bu değeri, abone (işlev ( bağımsız değişken ) {}) işlevinin içinde bir bağımsız değişken olarak elde edebilirsiniz .

Yazdırmak istiyorsanız, o zaman

subscribe( function (argument) {
    console.log(argument)
   } 
)
    import { Component, OnInit } from '@angular/core';
    import { pipe } from 'rxjs';
    import { Observable, of } from 'rxjs';
    import { map } from 'rxjs/operators';
    
    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html',
      styleUrls: [ './app.component.css' ]
    })
    export class AppComponent implements OnInit  {
    
      obs = of(1,2,3).pipe(
      map(x => x + 1),
      ); 
    
      constructor() { }
    
      ngOnInit(){  
        this.obs.subscribe(value => console.log(value))
      }
    }

https://stackblitz.com/edit/angular-ivy-plifkg

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.