কীভাবে আরএক্সজেএস সাবজেক্ট বা পর্যবেক্ষনের বর্তমান মূল্য পাবেন?


206

আমার একটি কৌনিক 2 পরিষেবা রয়েছে:

import {Storage} from './storage';
import {Injectable} from 'angular2/core';
import {Subject}    from 'rxjs/Subject';

@Injectable()
export class SessionStorage extends Storage {
  private _isLoggedInSource = new Subject<boolean>();
  isLoggedIn = this._isLoggedInSource.asObservable();
  constructor() {
    super('session');
  }
  setIsLoggedIn(value: boolean) {
    this.setItem('_isLoggedIn', value, () => {
      this._isLoggedInSource.next(value);
    });
  }
}

সবকিছু দুর্দান্ত কাজ করে। তবে আমার কাছে আরও একটি উপাদান রয়েছে যা সাবস্ক্রাইব করার দরকার নেই, এটির জন্য একটি নির্দিষ্ট সময়ে নির্দিষ্ট সময়ে আইলোগডইনের বর্তমান মান পাওয়া দরকার। কিভাবে আমি এটি করতে পারব?

উত্তর:


341

Subjectবা Observableবর্তমান মান নেই। যখন কোনও মান নির্গমন হয়, এটি গ্রাহকদের হাতে দেওয়া হয় এবং এটি Observableদিয়ে এটি করা হয়।

আপনি যদি কোনও বর্তমান মান রাখতে চান তবে BehaviorSubjectঠিক সেই উদ্দেশ্যেই নকশাকৃত ব্যবহার করুন। BehaviorSubjectসর্বশেষ নির্গত মান রাখে এবং তা নতুন গ্রাহকদের কাছে অবিলম্বে নির্গত করে।

getValue()বর্তমান মান পেতে এটির একটি পদ্ধতিও রয়েছে has


1
হাই, এটি আমার খারাপ, rxjs এ এখন তারা একই জিনিস 5. উপরের উত্স কোড লিঙ্কটি rxjs4 উল্লেখ করছে।
স্ক্রোডিঞ্জারের কোড

84
আরএক্সজেএস 5 এর লেখকের গুরুত্বপূর্ণ নোট: ব্যবহার করা getValue()হ'ল একটি বিশাল লাল পতাকা যা আপনি কিছু ভুল করছেন। এটি একটি পালানোর হ্যাচ হিসাবে আছে। সাধারণত আপনি আরএক্সজেএসের সাথে যা কিছু করেন তা ঘোষণামূলক হতে হবে। getValue()জরুরী। আপনি যদি ব্যবহার করে থাকেন তবে getValue()এখানে 99.9% সুযোগ রয়েছে যা আপনি কিছু ভুল বা অদ্ভুত করছেন।
বেন লেশ

1
@ বেনল্যাশ যদি আমার কাছে একটি থাকে BehaviorSubject<boolean>(false)এবং এটি টগল করা পছন্দ হয় তবে?
বব

3
অনিক্লিক-> ডিসপ্যাচটোসার্ভার (x.getValue ()) এর মতো একটি তাত্ক্ষণিক কাজ করার জন্য @ বেনল্যাশ গেটভ্যালু () খুব দরকারী, তবে এটি পর্যবেক্ষণযোগ্য চেইনে ব্যবহার করবেন না।
ফ্ল্যাভরস্কেপ

2
@ ইনগোবার্ক আপনার পরামর্শকে ন্যায্য প্রমাণ করার একমাত্র উপায় হ'ল যদি আপনি না জানতেন যে এটি foo$ছিল BehaviorSubject(যেমন এটি সংজ্ঞায়িত করা Observableহতে পারে এবং এটি কোনও স্থগিত উত্স থেকে গরম বা শীতল)। তবে যেহেতু আপনি তারপর ব্যবহার করার জন্য যেতে .nextউপর $fooনিজেই মানে হল আপনার বাস্তবায়ন এটা উপর নির্ভর হচ্ছে একটি BehaviorSubjectতাই শুধু ব্যবহার করছে না জন্য কোন যুক্তি নেই .valueপ্রথম স্থানে বর্তমান মান জন্য।
সাইমন_উইভার

144

একমাত্র উপায় আপনি উচিত মান পেয়ে হবে "বাইরে" একটি লক্ষণীয় / সাপেক্ষে সাবস্ক্রাইব সাথে আছেন!

আপনি যদি getValue()ঘোষণামূলক দৃষ্টান্তে অপরিহার্য কিছু করছেন আপনি ব্যবহার করছেন। এটি একটি পালানোর হ্যাচ হিসাবে রয়েছে, তবে আপনার ব্যবহার করা উচিত নয় এমন 99.9% সময় getValue()কয়েকটি আকর্ষণীয় বিষয় যা getValue()করবে: এটি সাবস্ক্রাইব করা না থাকলে এটি একটি ত্রুটি ছুঁড়ে দেয়, বিষয়টি মারা যাওয়ার কারণে এটি আপনাকে মূল্য পেতে বাধা দেবে কারণ এটি ভুল করা হয়েছে ইত্যাদি But বিরল পরিস্থিতিতে হ্যাচ।

"আরএক্স-ওয়াই" উপায়ে সাবজেক্ট বা অবজারভেবলের কাছ থেকে সর্বশেষ মানটি পাওয়ার বেশ কয়েকটি উপায় রয়েছে:

  1. ব্যবহার BehaviorSubject: তবে বাস্তবে এটিতে সাবস্ক্রাইব করা । আপনি যখন BehaviorSubjectএটিতে প্রথম সাবস্ক্রাইব করবেন ততক্ষণে এটি প্রাপ্ত বা প্রবর্তিত পূর্বের মানটি সিঙ্ক্রোনালি পাঠিয়ে দেবে।
  2. একটি ব্যবহার করে ReplaySubject(N): এটি Nমানগুলি ক্যাশে করবে এবং তাদের নতুন গ্রাহকদের কাছে পুনরায় খেলবে।
  3. A.withLatestFrom(B): পর্যবেক্ষণযোগ্য Bযখন Aনির্গত হয় তখন পর্যবেক্ষণযোগ্য থেকে সর্বাধিক সাম্প্রতিক মানটি পেতে এই অপারেটরটি ব্যবহার করুন । একটি অ্যারে আপনাকে উভয় মান প্রদান করবে [a, b]
  4. A.combineLatest(B): এই অপারেটর ব্যবহার থেকে সাম্প্রতিকতম মান পেতে Aএবং Bপ্রত্যেক সময় পারেন Aবা Bনির্গত। একটি অ্যারে আপনাকে উভয় মান প্রদান করবে।
  5. shareReplay(): এ এর ​​মাধ্যমে একটি পর্যবেক্ষণযোগ্য মাল্টিকাস্ট তৈরি করে ReplaySubjectতবে আপনাকে ত্রুটিযুক্ত করে পর্যবেক্ষণযোগ্যদের আবার চেষ্টা করার অনুমতি দেয়। (মূলত এটি আপনাকে সেই প্রতিশ্রুতি- y ক্যাচিং আচরণ দেয়)।
  6. publishReplay(), publishBehavior(initialValue), multicast(subject: BehaviorSubject | ReplaySubject), ইত্যাদি: অন্য অপারেটরদের যে লিভারেজ BehaviorSubjectএবং ReplaySubject। একই জিনিসটির বিভিন্ন স্বাদ, তারা মূলত কোনও বিষয়ের মাধ্যমে সমস্ত বিজ্ঞপ্তি ফানেল করে পর্যবেক্ষণযোগ্য উত্সটি মাল্টিকাস্ট করে। connect()বিষয়টির সাথে উত্সটি সাবস্ক্রাইব করার জন্য আপনাকে কল করতে হবে।

19
getValue () ব্যবহার করা কেন একটি লাল পতাকা? আমার যদি কেবল একবার পর্যবেক্ষণের বর্তমান মান প্রয়োজন হয়, এই মুহুর্তে ব্যবহারকারী কোনও বোতামটি ক্লিক করে? আমি কি মূল্যটির জন্য সাবস্ক্রাইব করে অবিলম্বে সাবস্ক্রাইব করা উচিত?
শিখা

5
এটা ঠিক আছে। তবে প্রায়শই এটি একটি চিহ্ন যে কোডটির লেখক খুব প্রয়োজনীয় কিছু করছে (সাধারণত পার্শ্ব-প্রতিক্রিয়া সহ) যেখানে সেগুলি হওয়া উচিত নয়। click$.mergeMap(() => behaviorSubject.take(1))আপনার সমস্যা সমাধানের জন্য আপনিও করতে পারেন ।
বেন লেশ

1
দুর্দান্ত ব্যাখ্যা! আসলে, আপনি যদি পর্যবেক্ষণযোগ্য রাখতে পারেন এবং পদ্ধতিগুলি ব্যবহার করতে পারেন তবে এটি আরও অনেক ভাল উপায়। পর্যবেক্ষণযোগ্য সহ সর্বত্র ব্যবহৃত টাইপস্ক্রিপ্টের প্রসঙ্গে তবে কেবলমাত্র কয়েকটি যা BehaviourSubject হিসাবে সংজ্ঞায়িত হয়েছে, তবে এটি কম সংক্ষিপ্ত কোড হবে। আপনার প্রস্তাবিত পদ্ধতিগুলি আমাকে সর্বত্র পর্যবেক্ষণযোগ্য প্রকারের রাখার অনুমতি দেয়।
জেএলভোই

2
এটি ভাল যদি আপনি কেবলমাত্র বর্তমান মানটি প্রেরণ করতে চান (যেমন ক্লিক করে সার্ভারে এটি প্রেরণ করুন), একটি getValue () করা খুব সহজ। তবে পর্যবেক্ষণযোগ্য অপারেটরদের শৃঙ্খলিত করার সময় এটি ব্যবহার করবেন না।
ফ্ল্যাওয়ারস্কেপ

1
আমার একটি রয়েছে AuthenticationServiceযা BehaviourSubjectবর্তমান লগইন অবস্থায় থাকা অবস্থায় ( boolean trueবা false) সংরক্ষণ করতে ব্যবহার করে। এটি isLoggedIn$এমন গ্রাহকদের জন্য একটি পর্যবেক্ষণযোগ্য উন্মোচন করে যারা কখন রাষ্ট্র পরিবর্তন হয় তা জানতে চায়। এটি এমন একটি get isLoggedIn()সম্পত্তিও উন্মোচিত করে , যা getValue()অন্তর্নিহিতকে কল করে বর্তমান লগ ইন করা অবস্থায় ফিরিয়ে দেয় BehaviourSubject- বর্তমান অবস্থাটি পরীক্ষা করতে এটি আমার প্রমাণীকরণ গার্ড দ্বারা ব্যবহৃত হয়। এটি getValue()আমার কাছে বোধগম্য ব্যবহারের মতো মনে হচ্ছে ...?
ড্যান কিং

11

আমার অনুরূপ পরিস্থিতি হয়েছিল যেখানে দেরিতে গ্রাহকরা সাবজেক্টটির মূল্য আসার পরে সাবস্ক্রাইব করে।

আমি রিপ্লেসউবজেক্টটি পেয়েছি যা এই আচরণে মনোভাবের মতো কাজ করে আচরণবিধির সাথে সমান। এবং এখানে আরও ভাল ব্যাখ্যার একটি লিঙ্ক: http://reactivex.io/rxjs/manual/overview.html#replaysubject


1
এটি আমার Angular4 অ্যাপ্লিকেশনটিতে আমাকে সহায়তা করেছিল - আমাকে কন্ট্রাক্টর কনস্ট্রাক্টর থেকে সাবস্ক্রিপশনটি এনজিওআইনিট () যেমন (এই উপাদানটি রুটগুলি জুড়ে ভাগ করা হয়েছে) এ স্থানান্তরিত করতে হয়েছিল, কারওর সাথে যদি একই সমস্যা হয় তবে কেবল এখানে ছেড়ে চলেছি
লুকা

1
আমার একটি অ্যাঙ্গুলার 5 অ্যাপের সাথে একটি সমস্যা ছিল যেখানে আমি একটি এপিআই থেকে মান পেতে বিভিন্ন পরিষেবাতে ভেরিয়েবল সেট করতে একটি পরিষেবা ব্যবহার করছিলাম। আমি বিষয় / পর্যবেক্ষণযোগ্যগুলি ব্যবহার করছিলাম তবে কোনও রুট পরিবর্তনের পরে এটি মানগুলিকে চাপ দেবে না। রিপ্লেসউবজেক্ট ছিল সাবজেক্টের প্রতিস্থাপনের ড্রপ এবং সবকিছু সমাধান করা হয়েছিল।
জাফায়ারক্লল

1
নিশ্চিত করুন যে আপনি রিপ্লেসউবজেক্ট (1) ব্যবহার করছেন অন্যথায় নতুন গ্রাহকরা প্রতিটি পূর্ব নির্গত মান ক্রমানুসারে পাবেন - এটি রানটাইমের সময় সর্বদা সুস্পষ্ট নয়
ড্রেনাই

@ ড্রেনাই যতদূর আমি বুঝতে পেরেছি রিপ্লেউউজব্যাক্ট (1) আচরণ আচরণের মতোই আচরণ করে ()
কেফির এরেজ

একেবারে একই নয়, রিপ্লেসউবজেক্টটি যদি next()ফাংশনটি এখনও চালু না করা হয় তবে এটি সাবস্ক্রাইব করা হলে অবিলম্বে কোনও ডিফল্ট মান নির্গত হয় না , যদিও বিহ্যাভিউর সাবজেক্টটি করে। তাত্ক্ষণিক এমিটটি একটি দৃশ্যে ডিফল্ট মান প্রয়োগ করার জন্য খুব কার্যকরী হয়, যখন বেহিভিউর সাবজেক্টটি কোনও পরিষেবাতে পর্যবেক্ষণযোগ্য ডেটা উত্স হিসাবে ব্যবহৃত হয়
ড্রেনাই

4
const observable = of('response')

function hasValue(value: any) {
  return value !== null && value !== undefined;
}

function getValue<T>(observable: Observable<T>): Promise<T> {
  return observable
    .pipe(
      filter(hasValue),
      first()
    )
    .toPromise();
}

const result = await getValue(observable)
// Do the logic with the result
// .................
// .................
// .................

আপনি কীভাবে এখান থেকে এটি প্রয়োগ করবেন সে সম্পর্কে পুরো নিবন্ধটি পরীক্ষা করতে পারেন। https://www.imkrish.com/how-to-get-current-value-of-observable-in-a-clean-way/


3

আমি শিশু উপাদানগুলিতে একই সমস্যার মুখোমুখি হয়েছিলাম যেখানে প্রাথমিকভাবে এটির সাবজেক্টের বর্তমান মান থাকতে হবে, তারপরে পরিবর্তনগুলি শুনতে সাবজেক্টটি সাবস্ক্রাইব করুন। আমি কেবল পরিষেবাটিতে বর্তমান মান বজায় রাখছি যাতে এটি উপাদানগুলির অ্যাক্সেসের জন্য উপলব্ধ হয়, যেমন:

import {Storage} from './storage';
import {Injectable} from 'angular2/core';
import {Subject}    from 'rxjs/Subject';

@Injectable()
export class SessionStorage extends Storage {

  isLoggedIn: boolean;

  private _isLoggedInSource = new Subject<boolean>();
  isLoggedIn = this._isLoggedInSource.asObservable();
  constructor() {
    super('session');
    this.currIsLoggedIn = false;
  }
  setIsLoggedIn(value: boolean) {
    this.setItem('_isLoggedIn', value, () => {
      this._isLoggedInSource.next(value);
    });
    this.isLoggedIn = value;
  }
}

যে উপাদানটির বর্তমান মান প্রয়োজন তা কেবল পরিষেবা থেকে এটি অ্যাক্সেস করতে পারে, যেমন:

sessionStorage.isLoggedIn

এটি সঠিক অনুশীলন কিনা নিশ্চিত না :)


2
আপনার উপাদান উপাদানটিতে যদি কোন পর্যবেক্ষণযোগ্যের মান প্রয়োজন হয় তবে আপনি কেবল asyncপাইপটি ব্যবহার করতে পারেন ।
ইনগো বার্ক

2

অনুরূপ একটি খুঁজছেন উত্তর downvoted যায়নি। তবে আমি মনে করি যে আমি এখানে সীমিত ক্ষেত্রে পরামর্শ দিচ্ছি তা আমি ন্যায়সঙ্গত করতে পারি।


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

যদি এটি হয় তবে আপনি যখন subscribe, মানটি অবিলম্বে ফিরে আসবে।

সুতরাং আসুন আমরা আপনাকে একটি পরিষেবায় কল করেছি এবং সমাপ্তির পরে আপনি আপনার দোকান থেকে কোনও কিছুর সর্বশেষতম মূল্য পেতে চান, সম্ভবত এটি নির্গত হয় না :

আপনি এটি করার চেষ্টা করতে পারেন (এবং আপনার যতটা সম্ভব জিনিসগুলি পাইপের অভ্যন্তরে রাখা উচিত):

 serviceCallResponse$.pipe(withLatestFrom(store$.select(x => x.customer)))
                     .subscribe(([ serviceCallResponse, customer] => {

                        // we have serviceCallResponse and customer 
                     });

এটির সাথে সমস্যাটি হ'ল এটি পর্যবেক্ষণযোগ্য না হওয়া অবধি অবধি অবরুদ্ধ হবে যা সম্ভবত কখনও হতে পারে না।

আমি সম্প্রতি নিজেকে একটি পর্যবেক্ষণযোগ্য মূল্যায়ন করার প্রয়োজন খুঁজে পেয়েছিলাম কেবল তখনই যখন কোনও মান পাওয়া যায় এবং আরও গুরুত্বপূর্ণভাবে এটি সনাক্ত না করতে পেরে আমার প্রয়োজন হবে। আমি এটি করে শেষ করেছি:

 serviceCallResponse$.pipe()
                     .subscribe(serviceCallResponse => {

                        // immediately try to subscribe to get the 'available' value
                        // note: immediately unsubscribe afterward to 'cancel' if needed
                        let customer = undefined;

                        // whatever the secondary observable is
                        const secondary$ = store$.select(x => x.customer);

                        // subscribe to it, and assign to closure scope
                        sub = secondary$.pipe(take(1)).subscribe(_customer => customer = _customer);
                        sub.unsubscribe();

                        // if there's a delay or customer isn't available the value won't have been set before we get here
                        if (customer === undefined) 
                        {
                           // handle, or ignore as needed
                           return throwError('Customer was not immediately available');
                        }
                     });

নোট করুন যে উপরের সকলের জন্য আমি subscribeমান পেতে ব্যবহার করছি (যেমন @ বেন আলোচনা করেছেন)। .valueসম্পত্তি ব্যবহার করছি না , এমনকি যদি আমার একটি ছিল BehaviorSubject


1
বিটিডব্লিউ এটি কাজ করে কারণ ডিফল্টরূপে 'সময়সূচী' বর্তমান থ্রেড ব্যবহার করে।
সাইমন_ ওয়েভার

1

যদিও এটি অত্যধিক কিলিং শোনায়, তবে পর্যবেক্ষণযোগ্য ধরণের রাখতে এবং বয়লারপ্লেট হ্রাস করার জন্য এটি আরও একটি "সম্ভাব্য" সমাধান ...

আপনি পর্যবেক্ষণযোগ্যের বর্তমান মান পেতে আপনি সর্বদা এক্সটেনশন গিটার তৈরি করতে পারেন।

এটি করার জন্য আপনাকে টাইপিংস ডিক্লেয়ারেশন ফাইলে Observable<T>ইন্টারফেসটি প্রসারিত করতে global.d.tsহবে। তারপর বাস্তবায়ন এক্সটেনশন সংগ্রহকারী একটি observable.extension.tsফাইল এবং পরিশেষে আপনার আবেদন উভয় typings এবং এক্সটেনশন ফাইল অন্তর্ভুক্ত।

কীভাবে আপনার কৌনিক অ্যাপ্লিকেশনটিতে এক্সটেনশনগুলি অন্তর্ভুক্ত করতে হয় তা জানতে আপনি এই স্ট্যাক ওভারফ্লো উত্তরটি উল্লেখ করতে পারেন ।

// global.d.ts
declare module 'rxjs' {
  interface Observable<T> {
    /**
     * _Extension Method_ - Returns current value of an Observable.
     * Value is retrieved using _first()_ operator to avoid the need to unsubscribe.
     */
    value: Observable<T>;
  }
}

// observable.extension.ts
Object.defineProperty(Observable.prototype, 'value', {
  get <T>(this: Observable<T>): Observable<T> {
    return this.pipe(
      filter(value => value !== null && value !== undefined),
      first());
  },
});

// using the extension getter example
this.myObservable$.value
  .subscribe(value => {
    // whatever code you need...
  });

0

আপনি শেষ নির্গত মানটি পর্যবেক্ষণযোগ্য থেকে পৃথক করে সঞ্চয় করতে পারেন। তারপরে প্রয়োজনে পড়ুন।

let lastValue: number;

const subscription = new Service().start();
subscription
    .subscribe((data) => {
        lastValue = data;
    }
);

1
পর্যবেক্ষনের বাইরে কিছু জিনিস সঞ্চয় করার জন্য এটি একটি প্রতিক্রিয়াশীল পদ্ধতির নয়। পরিবর্তে পর্যবেক্ষণযোগ্য স্ট্রিমগুলির মধ্যে আপনার যতটা সম্ভব প্রবাহিত হওয়া উচিত।
ganqqwerty

0

এটি করার সর্বোত্তম Behaviur Subjectউপায়টি হ'ল এখানে একটি উদাহরণ:

var sub = new rxjs.BehaviorSubject([0, 1])
sub.next([2, 3])
setTimeout(() => {sub.next([4, 5])}, 1500)
sub.subscribe(a => console.log(a)) //2, 3 (current value) -> wait 2 sec -> 4, 5

0

একটি সাবস্ক্রিপশন তৈরি করা যেতে পারে এবং প্রথম নির্গত আইটেমটি নষ্ট হওয়ার পরে। পাইপ এমন একটি ফাংশন যা কোনও পর্যবেক্ষণযোগ্যটিকে তার ইনপুট হিসাবে ব্যবহার করে এবং অন্য পর্যবেক্ষণযোগ্যটিকে আউটপুট হিসাবে ফেরত দেয়, যখন প্রথম পর্যবেক্ষণযোগ্যটি পরিবর্তন না করে। কৌণিক 8.1.0। প্যাকেজ: "rxjs": "6.5.3","rxjs-observable": "0.0.7"

  ngOnInit() {

    ...

    // If loading with previously saved value
    if (this.controlValue) {

      // Take says once you have 1, then close the subscription
      this.selectList.pipe(take(1)).subscribe(x => {
        let opt = x.find(y => y.value === this.controlValue);
        this.updateValue(opt);
      });

    }
  }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.