কীভাবে একটি পর্যবেক্ষণযোগ্য ক্রম নির্গমণের আগে অপরটির জন্য অপেক্ষা করা যায়?


93

বলুন আমার Observableমতো একটি আছে :

var one = someObservable.take(1);

one.subscribe(function(){ /* do something */ });

তারপরে, আমার একটি সেকেন্ড রয়েছে Observable:

var two = someOtherObservable.take(1);

এখন, আমি চাই subscribe()থেকে two, কিন্তু আমি নিশ্চিত যে করতে চাই oneসামনে সম্পন্ন করেছে twoগ্রাহক বহিস্কার করা হয়।

twoদ্বিতীয়টি প্রথমটি সম্পন্ন হওয়ার অপেক্ষার জন্য আমি কোন ধরণের বাফারিং পদ্ধতিটি ব্যবহার করতে পারি ?

আমি মনে করি আমি সম্পূর্ণ twoনা হওয়া অবধি বিরাম দেখছি one


4
আমি বিশ্বাস করি এর উত্তরটি। এক্সস্টাস্ট ম্যাপ () পদ্ধতি তবে আমি কীভাবে এটি বাস্তবায়ন করতে হবে তা জানার ভান করব না - সম্পূর্ণ বিবরণ এখানে: ব্লগ.আঙ্গুলার- ইউনিভার্সিটি.আইও
পিটার

উত্তর:


56

কয়েকটি উপায় আমি ভাবতে পারি

import {take, publish} from 'rxjs/operators'
import {concat} from 'rxjs'

//Method one

var one = someObservable.pipe(take(1));
var two = someOtherObservable.pipe(take(1));
concat(one, two).subscribe(function() {/*do something */});

//Method two, if they need to be separate for some reason
var one = someObservable.pipe(take(1));
var two = someOtherObservable.pipe(take(1), publish());
two.subscribe(function(){/*do something */});
one.subscribe(function(){/*do something */}, null, two.connect.bind(two));

4
আমি ব্যবহার শেষ পর্যন্ত pauseএবং resumeপরিবর্তে publishএবং connectকিন্তু উদাহরণস্বরূপ দুই মূলত রুট আমি নেন হয়।
স্টিফেন

4
এই পদ্ধতিটি সর্বদা সাবস্ক্রাইব () - এর ভিতরে oneদ্বিতীয় ( two) এর আগে প্রথম পর্যবেক্ষণযোগ্য ( ) সমাধান করবে ?
জন

কেন ব্যবহার Observable.forkJoin()করবেন না ? এই লিঙ্কটি শিখুন learnrxjs.io/operators/combination/forkjoin.html
mspasiuk

18
ওপেনের প্রয়োজনীয়তা অনুযায়ী @ এমএসপাসিয়ুক, তারা প্রথমটি সম্পন্ন করার পরে কেবল দ্বিতীয়টি সাবস্ক্রাইব করতে চেয়েছিল । forkJoinএকসাথে সাবস্ক্রাইব।
পলপডানিয়েলস

18

যদি আপনি নিশ্চিত করতে চান যে মৃত্যুদন্ডের ক্রমটি বজায় রয়েছে তবে আপনি ফ্ল্যাটম্যাপ নিম্নলিখিত উদাহরণ হিসাবে ব্যবহার করতে পারেন

const first = Rx.Observable.of(1).delay(1000).do(i => console.log(i));
const second = Rx.Observable.of(11).delay(500).do(i => console.log(i));
const third = Rx.Observable.of(111).do(i => console.log(i));

first
  .flatMap(() => second)
  .flatMap(() => third)
  .subscribe(()=> console.log('finished'));

ফলাফলটি হবে:

"1"
"11"
"111"
"finished"

16

শেষ () সহ skipUntil ()

SkipUntil: অন্য পর্যবেক্ষণযোগ্য নির্গমন না হওয়া পর্যন্ত নির্গত আইটেমগুলিকে উপেক্ষা করুন

শেষ: সিক্যুয়েন্স থেকে সর্বশেষ মান নির্গমন করুন (অর্থাত্ এটি নির্গত না হওয়া পর্যন্ত অপেক্ষা করুন)

দ্রষ্টব্য যে পর্যবেক্ষণযোগ্য পাস থেকে নিঃসৃত যে কোনও কিছুই skipUntilএড়িয়ে যাওয়া বাতিল করে দেবে, এজন্য আমাদের last()প্রবাহটি সম্পূর্ণ হওয়ার অপেক্ষা করতে হবে - যুক্ত করতে হবে।

main$.skipUntil(sequence2$.pipe(last()))

অফিসিয়াল: https://rxjs-dev.firebaseapp.com/api/operators/skipUntil


সম্ভাব্য ইস্যু: নোট করুন যে কোনও কিছু নির্গত না হলে last()নিজেই ত্রুটি ঘটবেlast()অপারেটর একটি আছে defaultপ্যারামিটার কিন্তু শুধুমাত্র একটি বিধেয় সাথে ব্যবহার। আমি মনে করি যদি এই পরিস্থিতিটি আপনার জন্য সমস্যা হয়ে থাকে (যদি sequence2$নির্গত না করেই সম্পূর্ণ হতে পারে) তবে এর মধ্যে একটির কাজ করা উচিত (বর্তমানে অনির্ধারিত):

main$.skipUntil(sequence2$.pipe(defaultIfEmpty(undefined), last()))
main$.skipUntil(sequence2$.pipe(last(), catchError(() => of(undefined))

দ্রষ্টব্য যেটি undefinedনির্গত হওয়ার জন্য একটি বৈধ আইটেম, তবে আসলে কোনও মান হতে পারে। এছাড়াও লক্ষ করুন যে এটি পাইপটি পাইপের সাথে সংযুক্ত sequence2$এবং নন main$


খুব আনাড়ি ডেমো: কৌণিক- vgznak.stackblitz.io আপনার কনসোল ট্রে খোলার জন্য ক্লিক করতে হবে
সাইমন_উইভার

আপনার সিনট্যাক্সটি ভুল। skipUntil সরাসরি পর্যবেক্ষণযোগ্য সাথে সংযুক্ত করা যাবে না অন্যথায় আপনি নিম্নলিখিত ত্রুটিটি পাবেন: 'সম্পত্তি' স্কিপউন্টিল '' পর্যবেক্ষণযোগ্য <অন্য> 'টাইপটিতে বিদ্যমান নেই।' আপনাকে প্রথমে এটি পাইপ ()
লন্ডন 804

হ্যাঁ পাইপের প্রয়োজন হওয়ার আগে এটি একটি পুরানো উত্তর। এটি উল্লেখ করার জন্য ধন্যবাদ। আমি এখনই এটি আপডেট করব তবে আমি আমার ফোনে আছি। উত্তর সম্পাদনা করতে নির্দ্বিধায়।
সাইমন_উইভার

13

সুইচম্যাপের ফলাফল নির্বাচকটির সুবিধা নেওয়ার জন্য এখানে আরও একটি সম্ভাবনা রয়েছে

var one$ = someObservable.take(1);
var two$ = someOtherObservable.take(1);
two$.switchMap(
    /** Wait for first Observable */
    () => one$,
    /** Only return the value we're actually interested in */
    (value2, value1) => value2
  )
  .subscribe((value2) => {
    /* do something */ 
  });

যেহেতু স্যুইচম্যাপের ফলাফল নির্বাচক অবনতি হয়েছে, তাই এখানে একটি আপডেট সংস্করণ

const one$ = someObservable.pipe(take(1));
const two$ = someOtherObservable.pipe(
  take(1),
  switchMap(value2 => one$.map(_ => value2))
);
two$.subscribe(value2 => {
  /* do something */ 
});

8

এটি করার একটি পুনরায় ব্যবহারযোগ্য উপায় এখানে রয়েছে (এটি টাইপস্ক্রিপ্ট তবে আপনি এটি জেএসের সাথে মানিয়ে নিতে পারেন):

export function waitFor<T>(signal: Observable<any>) {
    return (source: Observable<T>) =>
        new Observable<T>(observer =>
            signal.pipe(first())
                .subscribe(_ =>
                    source.subscribe(observer)
                )
        );
}

এবং আপনি এটি কোনও অপারেটরের মতো ব্যবহার করতে পারেন:

var two = someOtherObservable.pipe(waitFor(one), take(1));

এটি মূলত এমন একটি অপারেটর যা সংকেত পর্যবেক্ষণযোগ্য প্রথম ইভেন্টটি প্রকাশ না হওয়া অবধি পর্যবেক্ষণযোগ্য উত্সের সাবস্ক্রাইবকে পিছনে দেয়।


এই পুনরায় ব্যবহারযোগ্য ফাংশনের একটি rxswift সংস্করণ আছে
sujith1406

6

যদি দ্বিতীয় পর্যবেক্ষণযোগ্য গরম থাকে তবে বিরতি / পুনঃসূচনা করার আরও একটি উপায় রয়েছে :

var pauser = new Rx.Subject();
var source1 = Rx.Observable.interval(1000).take(1);
/* create source and pause */
var source2 = Rx.Observable.interval(1000).pausable(pauser);

source1.doOnCompleted(function () { 
  /* resume paused source2 */ 
  pauser.onNext(true);
}).subscribe(function(){
  // do something
});

source2.subscribe(function(){
  // start to recieve data 
});

এছাড়াও আপনি বিরতি চলাকালীন ডেটা রাখতে বাফার সংস্করণ পসযোগ্য বাফার্ড ব্যবহার করতে পারেন ।


2

এখানে আরও একটি, তবে আমি আরও সোজাসাপ্টা এবং স্বজ্ঞাত বোধ করছি (বা যদি আপনি প্রতিশ্রুতিতে ব্যবহার হন তবে কমপক্ষে প্রাকৃতিক), পদ্ধতির কাছে। মূলত, আপনি Observable.create()মোড়ানোর জন্য oneএবং twoএকক পর্যবেক্ষণযোগ্য হিসাবে একটি পর্যবেক্ষণযোগ্য তৈরি করেন। এটি কীভাবে Promise.all()কাজ করতে পারে তার সাথে খুব মিল ।

var first = someObservable.take(1);
var second = Observable.create((observer) => {
  return first.subscribe(
    function onNext(value) {
      /* do something with value like: */
      // observer.next(value);
    },
    function onError(error) {
      observer.error(error);
    },
    function onComplete() {
      someOtherObservable.take(1).subscribe(
        function onNext(value) {
          observer.next(value);
        },
        function onError(error) {
          observer.error(error);
        },
        function onComplete() {
          observer.complete();
        }
      );
    }
  );
});

তো, এখানে কি চলছে? প্রথমত, আমরা একটি নতুন পর্যবেক্ষণযোগ্য তৈরি করি। Observable.create()যথাযথভাবে নামকরণ করা ফাংশনটি onSubscriptionপর্যবেক্ষককে (আপনি যে পরামিতিগুলি দিয়েছিলেন সেগুলি দিয়ে তৈরি subscribe()) পাস করা হয় , যা একটি নতুন প্রতিশ্রুতি তৈরির সময় অনুরূপ resolveএবং rejectএকক বস্তুর সাথে মিলিত হয়। এইভাবেই আমরা যাদুটিকে কাজ করি।

ইন onSubscription, আমরা প্রথম পর্যবেক্ষণযোগ্য সাবস্ক্রাইব (উপরের উদাহরণে, এটি বলা হয়েছিল one)। আমরা কীভাবে পরিচালনা করি nextএবং errorআপনার উপর নির্ভর করে তবে আমার নমুনায় প্রদত্ত ডিফল্টটি সাধারণত বলার উপযুক্ত হওয়া উচিত। যাইহোক, আমরা যখন completeইভেন্টটি পাই , যার অর্থ oneএখন সম্পন্ন হয়েছে, আমরা পরবর্তী পর্যবেক্ষণে সাবস্ক্রাইব করতে পারি; এর মাধ্যমে প্রথমটি সম্পূর্ণ হওয়ার পরে দ্বিতীয় পর্যবেক্ষণযোগ্যকে গুলি চালানো।

দ্বিতীয় পর্যবেক্ষনের জন্য প্রদত্ত উদাহরণ পর্যবেক্ষক মোটামুটি সহজ। মূলত, secondএখন আপনি twoওপি-তে যেমন কাজ করবেন বলে আশা করেন তার মতো কাজ করে। আরও সুনির্দিষ্টভাবে, কোনও ত্রুটি নেই বলে ধরে নিয়ে secondপ্রথম someOtherObservable(এবং কারণ take(1)) দ্বারা নির্গত প্রথম এবং কেবলমাত্র প্রথম মানটি নির্গত হবে complete

উদাহরণ

এখানে একটি সম্পূর্ণ, কার্যকারী উদাহরণ আপনি যদি আমার জীবনে বাস্তব জীবনে কাজ করতে দেখতে চান তবে আপনি অনুলিপি / পেস্ট করতে পারেন:

var someObservable = Observable.from([1, 2, 3, 4, 5]);
var someOtherObservable = Observable.from([6, 7, 8, 9]);

var first = someObservable.take(1);
var second = Observable.create((observer) => {
  return first.subscribe(
    function onNext(value) {
      /* do something with value like: */
      observer.next(value);
    },
    function onError(error) {
      observer.error(error);
    },
    function onComplete() {
      someOtherObservable.take(1).subscribe(
        function onNext(value) {
          observer.next(value);
        },
        function onError(error) {
          observer.error(error);
        },
        function onComplete() {
          observer.complete();
        }
      );
    }
  );
}).subscribe(
  function onNext(value) {
    console.log(value);
  },
  function onError(error) {
    console.error(error);
  },
  function onComplete() {
    console.log("Done!");
  }
);

আপনি যদি কনসোলটি দেখেন তবে উপরের উদাহরণটি মুদ্রণ করবে:

সম্পন্ন!


এটি আমার নিজস্ব কাস্টম ক্লাস্টার (টি, এক্স, ডি) অপারেটর তৈরি করার দরকার ছিল যা কেবলমাত্র প্রথম এক্স উত্স থেকে টাইমস্প্যান টি এর মধ্যে প্রসারণ করে এবং ডি বিলম্বের ফলে ব্যবধানে বেরিয়ে আসা ফলাফলগুলি নির্গত করে। ধন্যবাদ!
winkim00

আমি আনন্দিত যে এটি সাহায্য করেছিল, এটি খুব আলোকিত হয়েছিল যখন আমি এটিও উপলব্ধি করেছিলাম।
c1moore

2

এখানে টাইপস্ক্রিপ্ট সহ একটি কাস্টম অপারেটর লিখেছেন যা ফলাফল নির্গমন করার আগে একটি সংকেতের জন্য অপেক্ষা করে:

export function waitFor<T>(
    signal$: Observable<any>
) {
    return (source$: Observable<T>) =>
        new Observable<T>(observer => {
            // combineLatest emits the first value only when
            // both source and signal emitted at least once
            combineLatest([
                source$,
                signal$.pipe(
                    first(),
                ),
            ])
                .subscribe(([v]) => observer.next(v));
        });
}

আপনি এটি এর মতো ব্যবহার করতে পারেন:

two.pipe(waitFor(one))
   .subscribe(value => ...);

4
সুন্দর প্যাটার্ন! এমনকি আপনি থ্রি.পাইপও করতে পারেন (ওয়েটফোর্ড (এক), ওয়েটফোর (দুটি), নিন (1))
ডেভিড রিন্ক

1

ভাল, আমি জানি এটি বেশ পুরানো তবে আমি মনে করি আপনার যা প্রয়োজন হতে পারে তা হ'ল:

var one = someObservable.take(1);

var two = someOtherObservable.pipe(
  concatMap((twoRes) => one.pipe(mapTo(twoRes))),
  take(1)
).subscribe((twoRes) => {
   // one is completed and we get two's subscription.
})

0

আপনি মার্জম্যাপ (বা তার উপন্যাস ফ্ল্যাটম্যাপ ) অপারেটরটির মতো পূর্ববর্তী পর্যবেক্ষণযোগ্য ধন্যবাদ থেকে নির্গত ফলাফল ব্যবহার করতে পারেন :

 const one = Observable.of('https://api.github.com/users');
 const two = (c) => ajax(c);//ajax from Rxjs/dom library

 one.mergeMap(two).subscribe(c => console.log(c))

4
এখান থেকে: learnrxjs.io/learn-rxjs/operators/transformation/mittedmap - "যদি অভ্যন্তরীণ পর্যবেক্ষণের নিঃসরণ এবং সাবস্ক্রিপশন ক্রম গুরুত্বপূর্ণ হয়, কনট্যাটম্যাপ চেষ্টা করুন!"
gsziszi
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.