RxJS अनुक्रम वादा के बराबर है। तब ()?


84

मैंने वादे के साथ बहुत विकास किया और अब मैं आरएक्सजेएस में जा रहा हूं। RxJS का डॉक वादा श्रृंखला से पर्यवेक्षक अनुक्रम में स्थानांतरित करने के तरीके पर बहुत स्पष्ट उदाहरण प्रदान नहीं करता है।

उदाहरण के लिए, मैं आमतौर पर कई चरणों के साथ वादा श्रृंखला लिखता हूं, जैसे

// a function that returns a promise
getPromise()
.then(function(result) {
   // do something
})
.then(function(result) {
   // do something
})
.then(function(result) {
   // do something
})
.catch(function(err) {
    // handle error
});

मुझे RxJS शैली में इस वादे की श्रृंखला को कैसे लिखना चाहिए?

जवाबों:


81

डेटा प्रवाह के लिए (समतुल्य then):

Rx.Observable.fromPromise(...)
  .flatMap(function(result) {
   // do something
  })
  .flatMap(function(result) {
   // do something
  })
  .subscribe(function onNext(result) {
    // end of chain
  }, function onError(error) {
    // process the error
  });

एक वादा एक अवलोकन योग्य में परिवर्तित किया जा सकता है Rx.Observable.fromPromise

कुछ वादा ऑपरेटरों का सीधा अनुवाद है। उदाहरण के लिए RSVP.all, या jQuery.whenद्वारा प्रतिस्थापित किया जा सकता है Rx.Observable.forkJoin

ध्यान रखें कि आपके पास ऑपरेटरों का एक समूह है जो डेटा को अतुल्यकालिक रूप से बदलने और उन कार्यों को करने की अनुमति देता है जो आप वादों के साथ नहीं कर सकते हैं या करना बहुत कठिन है। Rxjs अपनी सभी शक्तियों को डेटा के एसिंक्रोनस अनुक्रमों के साथ प्रकट करता है (अनुक्रम (1 से अधिक अतुल्यकालिक मूल्य)।

त्रुटि प्रबंधन के लिए, विषय थोड़ा अधिक जटिल है।

  • कैच होते हैं और अंत में ऑपरेटर भी होते हैं
  • retryWhen त्रुटि के मामले में अनुक्रम दोहराने में भी मदद कर सकता है
  • आप onErrorफ़ंक्शन के साथ स्वयं ग्राहक की त्रुटियों से भी निपट सकते हैं ।

सटीक शब्दार्थ के लिए, दस्तावेज़ीकरण और उन उदाहरणों पर गहराई से नज़र डालें, जिन्हें आप वेब पर पा सकते हैं, या यहाँ विशिष्ट प्रश्न पूछ सकते हैं।

Rxjs के साथ त्रुटि प्रबंधन में गहराई तक जाने के लिए यह निश्चित रूप से एक अच्छा शुरुआती बिंदु होगा: https://xgrommx.github.io/rx-book/content/getting_started_with_rxjs/preating_and_querying_observable_ पड़ेगाट /error_handling.html


मैं हमेशा देखता हूं कि अवलोकन योग्य क्रम सदस्यता () के साथ समाप्त होता है। जैसा कि यह केवल अवलोकन योग्य वस्तु का एक कार्य है, क्या ऐसा करने का कोई कारण है? यह अनुक्रम शुरू करने के लिए कार्य है?
Haoliang यू

सटीक। यदि कोई पर्यवेक्षक सदस्यता से नहीं गुजरा है, तो आपका अवलोकन किसी भी डेटा का उत्सर्जन नहीं करेगा, इसलिए आप किसी भी डेटा प्रवाह को नहीं जीत पाएंगे।
537 पर user3743222

7
मैं आपको इस पर एक नज़र डालने की सलाह देता हूं: gist.github.com/staltz/868e7e9bc2a7b8c1f754 । आईटी अधिक स्वादिष्ट हो सकता है कि आधिकारिक डॉक्टर।
user3743222

3
Promise.thenके बजाय .flatMapहै .map
तामास हेगडस

1
FYI करें यह बिल्कुल बराबर नहीं है क्योंकि Promise3 से संस्करण की त्रुटियों को thenपकड़ा जाएगा catch। यहाँ वे नहीं हैं।
mik01aj

35

एक अधिक आधुनिक विकल्प:

import {from as fromPromise} from 'rxjs';
import {catchError, flatMap} from 'rxjs/operators';

fromPromise(...).pipe(
   flatMap(result => {
       // do something
   }),
   flatMap(result => {
       // do something
   }),
   flatMap(result => {
       // do something
   }),
   catchError(error => {
       // handle error
   })
)

यह भी ध्यान दें कि यह सब काम करने के लिए, आपको कहीं न कहीं subscribeइस पाइप की आवश्यकता Observableहै, लेकिन मुझे लगता है कि यह अनुप्रयोग के किसी अन्य भाग में संभाला गया है।


मैं RxJS के लिए बहुत नया हूं, लेकिन यह देखते हुए कि हम केवल यहां एक घटना की प्रारंभिक धारा के साथ काम कर रहे हैं, और mergeMap()इसलिए वास्तव में विलय करने के लिए कुछ भी नहीं है , मेरा मानना ​​है कि हम इस मामले में बिल्कुल एक ही चीज हासिल कर सकते हैं concatMap()या switchMap()। क्या मुझे यह सही लगा ...?
दान राजा

8

RxJs 6 का उपयोग करके मई 2019 को अपडेट करें

ऊपर दिए गए जवाबों से सहमत हैं, स्पष्टता जोड़ने के लिए RxJs v6 का उपयोग करके कुछ खिलौना डेटा और सरल वादों ( सेटटाइमआउट के साथ) के साथ एक ठोस उदाहरण जोड़ना चाहते हैं।

बस पास की गई आईडी को अपडेट करें (वर्तमान में हार्ड-कोड के रूप में 1) ऐसी चीज के लिए जो एरर हैंडलिंग लॉजिक को भी निष्पादित करने के लिए मौजूद नहीं है। महत्वपूर्ण रूप से, भी के उपयोग पर ध्यान दें ofसाथ catchErrorसंदेश।

import { from as fromPromise, of } from "rxjs";
import { catchError, flatMap, tap } from "rxjs/operators";

const posts = [
  { title: "I love JavaScript", author: "Wes Bos", id: 1 },
  { title: "CSS!", author: "Chris Coyier", id: 2 },
  { title: "Dev tools tricks", author: "Addy Osmani", id: 3 }
];

const authors = [
  { name: "Wes Bos", twitter: "@wesbos", bio: "Canadian Developer" },
  {
    name: "Chris Coyier",
    twitter: "@chriscoyier",
    bio: "CSS Tricks and CodePen"
  },
  { name: "Addy Osmani", twitter: "@addyosmani", bio: "Googler" }
];

function getPostById(id) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const post = posts.find(post => post.id === id);
      if (post) {
        console.log("ok, post found!");
        resolve(post);
      } else {
        reject(Error("Post not found!"));
      }
    }, 200);
  });
}

function hydrateAuthor(post) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const authorDetails = authors.find(person => person.name === post.author);
      if (authorDetails) {
        post.author = authorDetails;
        console.log("ok, post hydrated with author info");
        resolve(post);
      } else {
        reject(Error("Author not Found!"));
      }
    }, 200);
  });
}

function dehydratePostTitle(post) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      delete post.title;
      console.log("ok, applied transformation to remove title");
      resolve(post);
    }, 200);
  });
}

// ok, here is how it looks regarding this question..
let source$ = fromPromise(getPostById(1)).pipe(
  flatMap(post => {
    return hydrateAuthor(post);
  }),
  flatMap(post => {
    return dehydratePostTitle(post);
  }),
  catchError(error => of(`Caught error: ${error}`))
);

source$.subscribe(console.log);

उत्पादित आंकड़े:

ok, post found!
ok, post hydrated with author info
ok, applied transformation to remove title
{ author:
   { name: 'Wes Bos',
     twitter: '@wesbos',
     bio: 'Canadian Developer' },
  id: 1 }

प्रमुख भाग, सादा वादा नियंत्रण प्रवाह का उपयोग करते हुए निम्नलिखित के बराबर है:

getPostById(1)
  .then(post => {
    return hydrateAuthor(post);
  })
  .then(post => {
    return dehydratePostTitle(post);
  })
  .then(author => {
    console.log(author);
  })
  .catch(err => {
    console.error(err);
  });

1

अगर मुझे सही तरीके से समझ में आया है, तो आपका मतलब है कि मूल्यों का उपभोग करना, जिस स्थिति में आप sbuscribe का उपयोग करते हैं

const arrObservable = from([1,2,3,4,5,6,7,8]);
arrObservable.subscribe(number => console.log(num) );

इसके साथ ही, आप केवल अवलोकन का उपयोग करने के वादे का पालन कर सकते हैं, जैसा कि दिखाया गया है:

arrObservable.toPromise().then()

0

यदि getPromiseफ़ंक्शन एक स्ट्रीम पाइप के बीच में है, तो आपको इसे एक फ़ंक्शन में लपेटना चाहिए mergeMap, switchMapया concatMap(आमतौर पर mergeMap):

stream$.pipe(
   mergeMap(data => getPromise(data)),
   filter(...),
   map(...)
 ).subscribe(...);

यदि आप अपनी स्ट्रीम को getPromise()फिर से शुरू करना चाहते हैं, तो इसे fromफंक्शन में लपेटें :

import {from} from 'rxjs';

from(getPromise()).pipe(
   filter(...)
   map(...)
).subscribe(...);

0

जहां तक ​​मुझे अभी पता चला है, यदि आप एक फ्लैटपाइप में परिणाम लौटाते हैं, तो यह इसे एक ऐरे में परिवर्तित करता है, भले ही आपने एक स्ट्रिंग लौटाया हो।

लेकिन अगर आप एक ऑब्जर्वेबल लौटाते हैं, तो वह ऑब्जर्वेबल एक स्ट्रिंग लौटा सकता है;


0

मैंने इस तरह से इसे किया।

इससे पहले

  public fetchContacts(onCompleteFn: (response: gapi.client.Response<gapi.client.people.ListConnectionsResponse>) => void) {
    const request = gapi.client.people.people.connections.list({
      resourceName: 'people/me',
      pageSize: 100,
      personFields: 'phoneNumbers,organizations,emailAddresses,names'
    }).then(response => {
      onCompleteFn(response as gapi.client.Response<gapi.client.people.ListConnectionsResponse>);
    });
  }

// caller:

  this.gapi.fetchContacts((rsp: gapi.client.Response<gapi.client.people.ListConnectionsResponse>) => {
      // handle rsp;
  });

बाद (ly?)

public fetchContacts(): Observable<gapi.client.Response<gapi.client.people.ListConnectionsResponse>> {
    return from(
      new Promise((resolve, reject) => {
        gapi.client.people.people.connections.list({
          resourceName: 'people/me',
          pageSize: 100,
          personFields: 'phoneNumbers,organizations,emailAddresses,names'
        }).then(result => {
          resolve(result);
        });
      })
    ).pipe(map((result: gapi.client.Response<gapi.client.people.ListConnectionsResponse>) => {
      return result; //map is not really required if you not changing anything in the response. you can just return the from() and caller would subscribe to it.
    }));
  }

// caller

this.gapi.fetchContacts().subscribe(((rsp: gapi.client.Response<gapi.client.people.ListConnectionsResponse>) => {
  // handle rsp
}), (error) => {
  // handle error
});

खराब असर : कॉलबैक को ऑब्जर्वेबल में बदलने के बाद बदलाव का पता भी चलने लगा
आनंद रॉकजॉन

0

RxJS अनुक्रम वादा के बराबर है। तब ()?

उदाहरण के लिए

function getdata1 (argument) {
        return this.http.get(url)
            .map((res: Response) => res.json());
    }

    function getdata2 (argument) {
        return this.http.get(url)
            .map((res: Response) => res.json());
    }

    getdata1.subscribe((data1: any) => {
        console.log("got data one. get data 2 now");
        getdata2.subscribe((data2: any) => {
            console.log("got data one and two here");
        });
    });
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.