(1) বনাম প্রথম () নিন


137

আমি AuthGuardব্যবহারের কয়েকটি বাস্তবায়ন পেয়েছি take(1)। আমার প্রকল্পে, আমি ব্যবহার করেছি first()

দুজনেই কি একইভাবে কাজ করে?

import 'rxjs/add/operator/map';
import 'rxjs/add/operator/first';
import { Observable } from 'rxjs/Observable';

import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { AngularFire } from 'angularfire2';

@Injectable()
export class AuthGuard implements CanActivate {

    constructor(private angularFire: AngularFire, private router: Router) { }

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
        return this.angularFire.auth.map(
            (auth) =>  {
                if (auth) {
                    this.router.navigate(['/dashboard']);
                    return false;
                } else {
                    return true;
                }
            }
        ).first(); // Just change this to .take(1)
    }
}

উত্তর:


197

অপারেটর first()এবং take(1)এক নয়।

first()অপারেটর একটি ঐচ্ছিক লাগে predicateফাংশন এবং একটি নির্গত errorযখন কোনো মূল্যই যখন উৎস সম্পন্ন মিলেছে বিজ্ঞপ্তি।

উদাহরণস্বরূপ এটি একটি ত্রুটি নির্গত করবে:

import { EMPTY, range } from 'rxjs';
import { first, take } from 'rxjs/operators';

EMPTY.pipe(
  first(),
).subscribe(console.log, err => console.log('Error', err));

... ঠিক এটার মতন:

range(1, 5).pipe(
  first(val => val > 6),
).subscribe(console.log, err => console.log('Error', err));

যদিও এটি নির্গত প্রথম মানের সাথে মিলবে:

range(1, 5).pipe(
  first(),
).subscribe(console.log, err => console.log('Error', err));

অন্যদিকে take(1)কেবল প্রথম মানটি নেয় এবং সম্পূর্ণ হয়। এর সাথে আর কোনও যুক্তি জড়িত নয়।

range(1, 5).pipe(
  take(1),
).subscribe(console.log, err => console.log('Error', err));

তারপরে খালি উত্স পর্যবেক্ষণযোগ্য এটি কোনও ত্রুটি ছাড়বে না:

EMPTY.pipe(
  take(1),
).subscribe(console.log, err => console.log('Error', err));

জানুয়ারী 2019: আরএক্সজেএস 6 এর জন্য আপডেট হয়েছে


2
শুধু নোট, আমি সেটা বলিনি first()এবং take()সাধারণভাবে একই, যা আমি মনে করি বেশ স্পষ্ট, শুধুমাত্র যে first()এবং take(1)একই। আপনার উত্তর থেকে আমি নিশ্চিত নই যদি আপনি ভাবেন যে এখনও কোনও পার্থক্য আছে?
গন্টার জ্যাচবাউয়ার

14
@ GünterZöchbauer আসলে, তাদের আচরণ আলাদা। যদি উত্সটি কোনও কিছু নির্গত না করে এবং সম্পূর্ণ করে তবে first()ত্রুটি বিজ্ঞপ্তি প্রেরণ করুন যখন take(1)কোনও কিছুই নির্গত হয় না।
মার্টিন

@ মার্টিন, কিছু ক্ষেত্রে (1) কোডটি ডিবাগ করা আরও শক্ত হবে বলার অর্থ কিছু ছাড়বে না?
করুবান

7
@ কারুবান এটি আপনার ইউসকেসের উপর নির্ভর করে। কোনও মান না পাওয়া যদি আমি ব্যবহার করার পরামর্শ দিই তবে অপ্রত্যাশিত first()। যদি এটি একটি বৈধ অ্যাপ্লিকেশন রাষ্ট্র হয় আমি যেতে চাই take(1)
মার্টিন

2
এই .NET এর অনুরূপ .First()বনাম .FirstOrDefault()এটা মনে করার (এবং আসা .Take(1)যে প্রথম সংগ্রহ কিছু প্রয়োজন এবং একটি খালি সংগ্রহের জন্য একটি ত্রুটি দেয় - এবং উভয় FirstOrDefault()এবং .Take(1)সংগ্রহটি ফাঁকা এবং বিনিময়ে হতে করার অনুমতি দেয় nullযথাক্রমে এবং খালি সংগ্রহ।
Simon_Weaver

45

পরামর্শ: কেবলমাত্র first()যদি ব্যবহার করুন :

  • আপনি শূন্য আইটেমকে নির্গত ত্রুটির শর্ত হিসাবে বিবেচনা করেন (উদাঃ প্রসারণের পূর্বে সম্পন্ন করা) এবং যদি 0% এরও বেশি ত্রুটির সম্ভাবনা থাকে তবে আপনি এটিকে দক্ষতার সাথে পরিচালনা করছেন
  • অথবা আপনি 100% জানেন যে উত্স পর্যবেক্ষণযোগ্য 1+ আইটেম নির্গত করবে (তাই কখনই ফেলতে পারে না)

যদি শূন্য নির্গমন হয় এবং আপনি সুস্পষ্টভাবে এটি পরিচালনা করছেন না (দিয়ে) catchError তবে) তবে সেই ত্রুটিটি প্রচারিত হবে, সম্ভবত অন্য কোথাও একটি অপ্রত্যাশিত সমস্যার কারণ হতে পারে এবং এটি ট্র্যাক করতে বেশ জটিল হতে পারে - বিশেষত যদি এটি শেষ ব্যবহারকারী থেকে আসে।

তুমি নিরাপদ ব্যবহার বন্ধ take(1)করে দেওয়া অধিকাংশ অংশ জন্য:

  • আপনি ঠিক আছেন take(1)উত্সটি নির্গমন ছাড়াই সম্পূর্ণ হয় তবে আপনি কিছু নির্গত না করে ।
  • আপনার কোনও ইনলাইন প্রিকিকেট ব্যবহার করার দরকার নেই (উদা। first(x => x > 10))

দ্রষ্টব্য: আপনি এর মতো একটি শিকারী ব্যবহার করতে পারেন take(1):.pipe( filter(x => x > 10), take(1) ) । যদি 10 এর চেয়ে বেশি কিছু না হয় তবে এটির সাথে কোনও ত্রুটি নেই।

কি সম্পর্কে single()

আপনি যদি আরও কঠোর হতে চান এবং দুটি নির্গমন নিষ্ক্রিয় করতে চান single()তবে শূন্য বা 2+ নির্গমন থাকলে কোন ত্রুটিগুলি ব্যবহার করতে পারেন । আবার আপনাকে সেই ক্ষেত্রে ত্রুটিগুলি পরিচালনা করতে হবে।

টিপ: Singleআপনি যদি পর্যবেক্ষণযোগ্য চেইনটি কোনও HTTP পরিষেবা দু'বার কল করা এবং দুটি পর্যবেক্ষণযোগ্য নির্গতের মতো অতিরিক্ত কাজ না করে তা নিশ্চিত করতে চান তবে মাঝে মাঝে দরকারী হতে পারে। singleপাইপের শেষে যুক্ত করা আপনাকে জানায় যে আপনি যদি এইরকম ভুল করেছেন। আমি এটি একটি 'টাস্ক রানার'-এ ব্যবহার করছি যেখানে আপনি পর্যবেক্ষণযোগ্য কোনও টাস্কে উত্তীর্ণ হন যা কেবলমাত্র একটি মান নির্গত করতে পারে, তাই আমি single(), catchError()ভাল আচরণের গ্যারান্টি দিয়ে সাড়া ফেলে দিয়েছি ।


সবসময় first()পরিবর্তে ব্যবহার করবেন না কেন take(1)?

ওরফে। কীভাবে first সম্ভাব্য আরও ত্রুটি ঘটতে পারে ?

আপনার যদি এমন পর্যবেক্ষণযোগ্য থাকে যা কোনও পরিষেবা থেকে কিছু নেয় এবং তারপরে এটি পাইপ দেয় তবে first()বেশিরভাগ সময় ভাল থাকতে হবে। তবে যদি কেউ যে কোনও কারণে পরিষেবাটি অক্ষম করতে আসে - এবং এটি নির্গমন of(null)বা NEVERতারপরে কোনও প্রবাহে পরিবর্তন করেfirst() অপারেটর ত্রুটি ছুঁড়তে শুরু করে।

এখন আমি বুঝতে পারি যে আপনি যা চান ঠিক তেমনই হতে পারে - তাই এটি কেবল একটি টিপ। অপারেটর firstআমার কাছে আবেদন করেছিলেন কারণ এটি তুলনায় কিছুটা কম 'আনাড়ি' বলে মনে হয়েছে take(1)তবে উত্সটি নির্গত না হওয়ার কোনও সম্ভাবনা থাকলে আপনার ত্রুটিগুলি পরিচালনা করার বিষয়ে সতর্ক হওয়া দরকার। আপনি যা করছেন তা পুরোপুরি নির্ভর করবে।


যদি আপনার ডিফল্ট মান থাকে (ধ্রুবক):

আপনার .pipe(defaultIfEmpty(42), first())যদি কোনও ডিফল্ট মান থাকে যা ব্যবহার করা উচিত যদি কিছু না বের হয় তবে তা বিবেচনা করুন। এটি অবশ্যই কোনও ত্রুটি বাড়ায় না কারণ এটিfirst তুলবে না সর্বদা একটি মান পাবে।

নোটটি defaultIfEmptyকেবল ট্রিগার করা হয় যদি স্ট্রিমটি খালি থাকে তবে যা নির্গত হয় তার মান হয় না null


singleআরও বেশি পার্থক্য রয়েছে সে সম্পর্কে সচেতন হন first1. এটি কেবলমাত্র মানটি নির্গত করবে complete। এর অর্থ হ'ল যদি পর্যবেক্ষণযোগ্য কোনও মান নির্ধারণ করে তবে কখনই সম্পূর্ণ হয় না তবে একক কখনই কোনও মান নির্গত করতে পারে না। ২. কোনও কারণে আপনি যদি কোনও ফিল্টার ফাংশন পাস singleকরেন যা কোনও কিছুর সাথে মেলে না undefinedতবে মূল সিকোয়েন্সটি খালি না থাকলে কোনও মান নির্গত হয়, যা ক্ষেত্রে হয় না first
মেরিনোস আন

28

এখানে তিনটি Observables হয় A, Bএবং Cমার্বেল ডায়াগ্রামে সঙ্গে পার্থক্য অন্বেষণ করতে first, takeএবং singleঅপারেটরদের:

প্রথম বনাম একক অপারেটর তুলনা তুলনা

* কিংবদন্তি :
--o-- মান
----! ত্রুটি
----| সমাপ্তি

এটির সাথে https://thinkrx.io/rxjs/first-vs-take-vs-single/ এ খেলুন ।

ইতিমধ্যে সমস্ত উত্তর রয়েছে, আমি আরও চাক্ষুষ ব্যাখ্যা যুক্ত করতে চেয়েছিলাম

আশা করি এটি কাউকে সাহায্য করবে


12

এর মধ্যে একটি সত্যই গুরুত্বপূর্ণ পার্থক্য রয়েছে যা কোথাও উল্লেখ করা হয়নি।

(1) 1 টি প্রকাশ করে, সম্পূর্ণ করে, সাবস্ক্রাইব করে

প্রথম () 1 টি প্রকাশ করে, সম্পূর্ণ করে তবে সাবস্ক্রাইব করে না।

এর অর্থ হ'ল আপনার প্রবাহ পর্যবেক্ষণযোগ্য প্রথম () এর পরেও গরম থাকবে যা সম্ভবত প্রত্যাশিত আচরণ নয়।

ইউপিডি: এটি আরএক্সজেএস 5.2.0 রেফারেন্স করে। এই ইস্যুটি ইতিমধ্যে স্থির থাকতে পারে।


আমি মনে করি না যে কোনও একটি সদস্যতা ছাড়লাম , jsbin.com/nuzulorota/1/edit?js,console দেখুন
ওয়েলটস্মার্জ

10
হ্যাঁ, উভয় অপারেটর সাবস্ক্রিপশনটি সম্পূর্ণ করেন, ত্রুটি পরিচালনার ক্ষেত্রে তফাতটি ঘটে। যদি সেই পর্যবেক্ষণযোগ্য মানগুলি নির্গমন করে না এবং এখনও প্রথম অপারেটরটি ব্যবহার করে প্রথম মানটি নেওয়ার চেষ্টা করে তবে এটি ত্রুটি ছুঁড়ে দেবে। সাবস্ক্রিপশনটি ঘটে যখন এটি স্ট্রিমের মধ্যে মান না থাকা সত্ত্বেও আমরা এটি (1) অপারেটর দিয়ে প্রতিস্থাপন করি তবে এটি ত্রুটি ছুঁড়ে না।
noelyahan

7
স্পষ্ট করতে: উভয়ই সাবস্ক্রাইব করে do @ ওয়েলচেচার্জারের উদাহরণটি খুব সরল করে দেওয়া হয়েছিল, এটি নিজের দ্বারা সাবস্ক্রাইব না করা অবধি চালিত হয় না। এইটি কিছুটা প্রসারিত: repl.it/repls/FrededHugeAudacity
স্টিফান এলভি

10

দেখে মনে হচ্ছে আরএক্সজেএস 5.2.0 এ .first()অপারেটরের একটি বাগ রয়েছে ,

সেই বাগের কারণে .take(1)এবং .first()আপনি যদি এগুলি ব্যবহার করে থাকেন তবে একেবারে অন্যরকম আচরণ করতে পারে switchMap:

সঙ্গে take(1)প্রত্যাশিত হিসাবে আপনি আচরণ পাবেন:

var x = Rx.Observable.interval(1000)
   .do( x=> console.log("One"))
   .take(1)
   .switchMap(x => Rx.Observable.interval(1000))
   .do( x=> console.log("Two"))
   .subscribe((x) => {})

// In the console you will see:
// One
// Two
// Two
// Two
// Two
// etc...

তবে আপনার সাথে .first()ভুল আচরণ পাবেন:

var x = Rx.Observable.interval(1000)
  .do( x=> console.log("One"))
  .first()
  .switchMap(x => Rx.Observable.interval(1000))
  .do( x=> console.log("Two"))
  .subscribe((x) => {})

// In console you will see:
// One
// One
// Two
// One
// Two
// One
// etc... 

কোডেপেনের একটি লিঙ্ক এখানে' s

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