Combining RxJS Promises (transferring information)

As a newcomer to Rx, I am struggling to locate documentation on how to compose promises where the data from the first promise is passed into the second one and so forth. Here are three basic promises with asynchronous operations involving previous data:

 const p1 = () => Promise.resolve(1);
 const p2 = x => {const val = x + 1; return Promise.resolve(val);};
 const p3 = x => {
      const isEven = x => x % 2 === 0;
      return Promise.resolve(isEven(x));
 };

The traditional method to achieve this composition is by chaining promises like this:

 pl().then(p2).then(p3).then(console.log);

A preferred implementation for me is using Ramda's composeP and pipeP:

R.pipeP(p1, p2, p3, console.log)()

While it seems likely that Rx could handle such situations smoothly, the closest example I've found so far involves RxJS and async operations:

 var Rx = require('rx'),
     fs = require('fs'),
     path = require('path');
 var file = path.join(__dirname, 'file.txt'),
     dest = path.join(__dirname, 'file1.txt'),
     exists = Rx.Observable.fromCallback(fs.exists),
     rename = Rx.Observable.fromNodeCallback(fs.rename),
     stat = Rx.Observable.fromNodeCallback(fs.stat);
 exists(file)
    .concatMap(function (flag) {
     return flag ?
         rename(file, dest) :
         Rx.Observable.throw(new Error('File does not exist.'));
    })
    .concatMap(function () {
        return stat(dest);
    })
   .forEach(
      function (fsStat) {
          console.log(JSON.stringify(fsStat));
      },
      function (err) {
          console.log(err);
      }
    );

Although concatMap appears promising, the complexity of the above code is notable. I encountered issues in my own example as well because Rx.Observable.fromPromise(p1) expects a promise instead of a function, and Rx.Observable.defer(p1) doesn't seem to handle parameters properly.

Thank you for any insights!

For a related question without data passing, check out: Chaining promises with RxJS

Answer №1

I skimmed through the text, but if you're looking to achieve similar functionality as

pl().then(p2).then(p3).then(console.log);
, where p represents functions returning promises, you could try something like this (check out an example here):

Rx.Observable.fromPromise(p1())
             .flatMap(function(p1_result){return p2(p1_result);})
             .flatMap(function(p2_result){return p3(p2_result);})

Alternatively, a more balanced approach:

 var chainedPromises$ = 
     Rx.Observable.just()
             .flatMap(p1)
             .flatMap(p2)
             .flatMap(p3);

If you want to sequentially execute callback functions wrapped in fromCallback or fromNodeCallback, you could try something like this:

function rename (flag){
  return flag
          ? rename(file,dest).flatMap(return Rx.Observable.just(dest))
          : Rx.Observable.throw(new Error('File does not exist.'));
}

Rx.Observable.just(file)
             .flatMap(exists)
             .flatMap(rename)
             .flatMap(stat)

The latter code hasn't been tested, so please let me know if it works for you. One last thing, this method should work fine if only one value is produced at each step (similar to a promise). If you have multiple files instead of just one, using flatMap might cause ordering issues (if order matters to you), in which case, consider using concatMap instead.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Prevent certain individuals from selecting a checkbox within HTML forms

Currently, I have a form where users need to fill in their information. However, I want certain parts of the form to be preventable based on the level of access the user has. For example, I have successfully implemented a code snippet onfocus='blur() ...

Timeout feature for image slider in Angular JS

Hey there, I've been trying to get my AngularJS image slider to work like a slideshow where the images transition smoothly from slide to slide. I managed to code the functionality for navigating to the next and previous images, but when I attempted to ...

Struggling to remove an image while using the onmouseover event with a button?

I am encountering an issue with hiding an image using the onmouseover event not applied directly to it, but rather to a button element. The desired functionality is for the image to appear when the mouse hovers over and disappear when it moves away. Here&a ...

Techniques for transferring images directly into HTML canvas games

I created a thrilling race car game and here is the code snippet: index.html <!DOCTYPE html> <html> <head> <title> Extreme Race Car Game </title> <link rel="stylesheet" type="text/css" href="style.css"> < ...

Are there any techniques for running unit tests on a Vue.js transition?

I have been working on a Vue component that includes a transition with a dynamically generated name. My challenge is to test whether the transition name is correctly set based on the props I pass into the component. Below is the code snippet of the compone ...

Modifying email alters the appearance of the input element

Utilizing labels as placeholder text behind input boxes with a transparent background, changing to white on :focus and when input value is > 0, I created a contact form. However, integrating PHP into the form recently caused styling issues. Although I m ...

What methods can I use to integrate a Google HeatMap into the GoogleMap object in the Angular AGM library?

I am trying to fetch the googleMap object in agm and utilize it to create a HeatMapLayer in my project. However, the following code is not functioning as expected: declare var google: any; @Directive({ selector: 'my-comp', }) export class MyC ...

What could be the reason for receiving [object object] from a JSON response?

Utilizing the datatables plugin, I am in need of refilling the table with ajax. To achieve this, I populate the table columns with the data retrieved from an ajax file (in json format) as shown in the following code snippet: $.get(select.data('url&a ...

The absence of the map function in Rxjs is evident despite its import

Many people have encountered the issue of "map is not a function" when working with RxJS, usually due to not importing the rxjs library. In my situation, I have imported the library correctly but still face the same error. I am currently using Ionic 2 an ...

The Malihu jQuery Custom Scrollbar integrated with Meteor is failing to display on the webpage

I have successfully integrated Malihu's custom scrollbar into my meteor app using this package: The code I'm using is as follows: Template.post.rendered = function() { $('body').mCustomScrollbar({ theme: 'minimal-dar ...

Parsing JSON in an Express application

I have developed a small application to test a larger one that I am currently working on. The small application reads data from a CSV file and then attempts to send this data to my API endpoint using POST requests. This is necessary as I need to send a lar ...

Is the HTML Page loading before the AJAX call is made?

On my HTML Page, I have a button tag that looks like this: <button ng-hide="alreadyFreinds()" type="button" class="btn btn-primary btn-lg">Friend</button> However, when attempting to access certain parts of the alreadyFriends function shown b ...

From traditional relational databases to MongoDB/Mongoose database design

Recently, I ventured into using mongoDB and mongoose for a new node.js application. Coming from a background of relational databases, I find it challenging to adjust to the mongoDB/noSQL approach, particularly concerning denormalization and the absence of ...

What is the best way to retrieve the value or text from a dropdown menu that has been added to a table row using JQuery?

Within my dynamic table, users can click an "add" button to generate a new row in the table using JQuery. One of the columns in each new row includes a dropdown box with predefined values. How can I retrieve the selected value from this dynamically created ...

tsconfig.json: No input files were detected in the configuration file

I am encountering an issue with my tsconfig.ts file where it says "No inputs were found in config file 'd:/self-study/Web/Learning/Express/tsconfig.json'. Specified 'include' paths were '["**/*"]' and 'exclude&a ...

How to implement flash messages in Node.js forms submission process

Recently, I've been attempting to implement a Bootstrap style alert that appears after submitting a contact form using Node JS/Express. My view is based on an ejs template. mailerRoutes.js const nodemailer = require('nodemailer'); const ma ...

Is there a way for me to display a gif similar to 9GAG on my

I'm looking to implement a feature on my website that allows me to pause and play a gif, similar to the functionality on 9gag. Can anyone provide guidance on how I can achieve this? I understand that I need to use both .jpg and .gif files, but my at ...

Error 422: Issues with posting Laravel ajax form on Microsoft Edge browser

I am facing an issue with a form that I have implemented in my Laravel controller. The form works perfectly fine on Chrome, Safari, and Firefox, but it gives a 422 (unprocessable entity) error on Edge browser. Could someone help me figure out what might b ...

Transfer all the child nodes to the parent using the spread operator or Object.assign while preventing duplicate properties from being overwritten

I'm trying to transfer all the nodes of a child node to the parent using the spread operator or Object.assign (without relying on Lodash) while avoiding overwriting existing properties. My initial thought was to simply append the childArray to the ro ...

What is the best way to search a map object that serves as the document ID in Firebase?

I am attempting to retrieve all fieldnames within the payload > (random doc id) objects. https://i.sstatic.net/y9703.png At this moment, my approach involves fetching other collections using the following code: async fetchPage() { const query = fir ...