Merge topics together in RxJS like zip

Is it possible to create an observable that combines two subjects in a unique way, different from the zip function?

The goal is to combine two subjects so that when both have emitted values, the latest of their values is emitted. Then, after both emit at least once more, the latest values are emitted again, and so on.

Visual representation:

1 ---------- 2 ----- 3 -- 4 ------------------- 5 ——

------- a ------------------- b --- c — d —-————

Desired output:

------- 1a ----------------- 4b ---————-5d —-

For example, if subject1 emits 5 times and then subject2 emits once, the first emitted value would be a pair of both subjects' initial emissions: (subj1-emit5, subj2-emit1).

Answer №1

If you want to accomplish your goal easily, consider using the `combineLatest()` function along with `take(1)` and then add the `repeat()` operator to resubscribe after each sequence:

import { Subject, combineLatest, take, repeat } from 'rxjs';

const s1$ = new Subject<number>();
const s2$ = new Subject<string>();

combineLatest([s1$, s2$]).pipe(
  take(1),
  repeat(),
).subscribe(console.log);

setTimeout(() => s1$.next(1), 0);
setTimeout(() => s2$.next('a'), 200);
setTimeout(() => s1$.next(2), 300);
setTimeout(() => s1$.next(3), 400);
setTimeout(() => s1$.next(4), 500);
setTimeout(() => s2$.next('b'), 600);
setTimeout(() => s2$.next('c'), 700);
setTimeout(() => s2$.next('d'), 800);
setTimeout(() => s1$.next(5), 900);

// Output: [1, 'a'], [4, 'b'], [5, 'd']

Check out the live demo here: https://stackblitz.com/edit/rxjs-4vg6lu?devtoolsheight=60&file=index.ts

Answer №2

To start creating an almostZip function, I would approach it like this (detailed comments are included within the code to explain the process)

function almostZip(o1$: Observable<any>, o2$: Observable<any>) {
  // A variable is set in the closure to maintain the state of the Observable
  // Specifically, it stores the values emitted by the 2 input Observables
  const valuesEmitted = [null, null]
  const _o1$ = o1$.pipe(
    // When o1$ emits, the emitted value is stored in the first position of the state variable
    tap(v => valuesEmitted[0] = v)
  )
  const _o2$ = o2$.pipe(
    // When o2$ emits, the emitted value is stored in the second position of the state variable
    tap(v => valuesEmitted[1] = v)
  )

  // This is the Observable returned by almostZip function
  return merge(_o1$, _o2$).pipe(
    // Filter out all notifications until both slots of the state var are not null
    // If both are not null, then we can notify the pair - as explained further down
    filter(() => {
      return !!valuesEmitted[0] && !!valuesEmitted[1]
    }),
    // Notify a copy of the state
    // Emitting a copy of the state is necessary to reset the state soon after
    map(() => [...valuesEmitted]),
    // Reset the state
    // After notifying a pair of values from each Observable, the state needs to be reset
    // to prepare for the next pair of values
    tap(() => {
      valuesEmitted[0] = null
      valuesEmitted[1] = null
    }),
  )
}

You can see a demonstration of how this functions on this stackblitz link

Answer №3

What if we use the withLatestFrom operator?

import './custom-style.css';

import { rx, of, tap, interval, withLatestFrom } from 'rxjs';
const stream1$ = interval(1000);
const stream2$ = interval(5000);

stream2$
  .pipe(
    withLatestFrom(stream1$),
    tap(([firstData, secondData]) => {
      console.log(`Data from second source (every 5 seconds): ${firstData}, Data from first source (every 1 second): ${secondData}`);
    })
  )
  .subscribe();

// Check the browser console for results.

Try it on StackBlitz

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

How can a JavaScript function be triggered by Flask without relying on any requests from the client-side?

I'm in the process of setting up a GUI server using Flask. The challenge I'm facing is integrating an API that triggers a function whenever there's a change in a specific Sqlite3 database. My goal is to dynamically update a table on the HTML ...

React - Refreshing a component with the help of another component

I've created a NavBar component that contains a list of links generated dynamically. These links are fetched from the backend based on specific categories and are stored within a child component of NavBar named DrawerMenu. The NavBar itself is a chil ...

Tips for adjusting image size to take up only half of the screen in NextJS

Struggling to resize an image to fit only 50% of the screen in NextJS? The Image component provided by NextJS comes with its own inline styling, making it tricky to customize. Currently, I attempt to style the image by wrapping the Image component in a spa ...

Population of the global namespace in JavaScript without the need for the 'new'

After watching the Douglas Crockford video on JavaScript, one thing that caught my attention was his explanation of what happens when you forget to use new for a class. He mentioned that doing so would populate the global namespace, which in the browser is ...

I am working on two Angular projects and I am looking to integrate one of them into the other project

In my development work, I am juggling two Angular projects on Github: AngularApp1 and AngularApp2. AngularApp1 is a robust project with many components, while AngularApp2 serves a more specific purpose. My goal is to have a button in AngularApp1 that open ...

Is there a way for me to manually manipulate the advancement of the progress bar from @ngx-progressbar/core in Angular5/Ionic4?

I've been working on implementing a progress bar into my application using the @ngx-progressbar/core library. However, I'm facing an issue where I can't seem to control its progress effectively. Whenever I try to increase the progress increm ...

Creating a PHP script that retrieves data from JavaScript and stores it in MySQL can be accomplished by using AJAX to send the

Hello, I am attempting to create a PHP script that can extract coordinates from this JavaScript code (or from this link ) and store them in a MySQL database. Can someone please provide me with a tutorial on how to accomplish this? <script> var ...

Guide on applying a filter to the items in a listbox using the input from a text box

In my HTML form, I have the following elements: 1) A list box containing filenames: s1.txt2013 s2.txt2013 s3.txt2012 s4.txt2012 2) A text box where the user enters a pattern (e.g. 2013) 3) A button By default, the list box contains the 4 file ...

Javascript code to verify whether the page is currently positioned at the top

How can I use JavaScript to determine if the page is at scroll(0,0)? I have a full-page slider that needs to pause when the page is no longer at the top. The page may not be scrolled manually, as there are internal HTML # links that could load the page d ...

The Angular Material Table is reporting an error: the data source provided does not conform to an array, Observable, or DataSource

Having some trouble with an Angular Material table, as I'm encountering an error preventing me from populating the grid: Error: Provided data source did not match an array, Observable, or DataSource search.service.ts GridSubmittedFilesList: IGridMo ...

What is the best way to store an image file using html/angularjs?

I'm facing a challenge in my app where I need to save an image on one page and then retrieve it on another. So far, I have explored three different methods but none of them seem to be working for me: First, I attempted to use 'Parse.File' w ...

The deployment of my Node application on Heroku is causing an error message: node-waf is not

I've been trying to deploy my Node.js application on Heroku by linking it to my Github repository and deploying the master branch. Despite experimenting with various methods, I keep encountering the same error every time. You can view the detailed b ...

Discover the magic of TransformToggle and slideToggle in Javascript, HTML, and CSS

Working on a website coding project and ran into an issue. Trying to utilize an img as a link to slideToggle content. It's working, but I'd like the img to rotate 90deg on the first click and -90deg on the second one. Any solutions are greatly ap ...

I must interact with the video within the iframe by clicking on it

I am trying to interact with an iframe video on a webpage. Here is the code snippet for the video: <div class="videoWrapper" style="" xpath="1"> <iframe width="854" height="480" src="xxxxxxx" frameborder="0" allow="autoplay; encrypted-media" all ...

Flask caches JSON files automatically

I am currently working on a visualization app using js and python. The functionality of my app is as follows: There is a textbox in the browser where I input an URL The URL is then sent to Python via Flask In Python, the URL is processed to create ...

What is the process for sending a message from the internet to a mobile device?

We are currently in the process of developing a website that sends SMS alerts to users for specific services, however I am struggling to set up a script that can perform this function. If anyone has any suggestions or recommendations for a solution, pleas ...

Uh oh! We encountered an error: Uncaught (in promise): Error: No routes found for the provided URL segment

There seems to be an issue with the router in my Angular application. I have successfully deployed it on an Apache server for production, and it is being served from the URL www.domain.com/clientng. Everything works fine, but I encounter an error in the br ...

Please ensure that the table contains all the records corresponding to the respective days

I am struggling with figuring out how to display a record of classes in my table view. The UX prototype I need to follow is shown https://i.stack.imgur.com/CISYn.png (the days of the week are in Portuguese: horario = time, segunda = Monday, terça = Tuesda ...

Converting ed25519 private key into OpenSSH Format using JavaScript

After generating an ed25519 key pair using the javascript crypto library, I am now faced with the challenge of saving the private key in openssh format. Despite attempting to use the sshpk library for this task, I encountered an issue where the exported k ...

Discovering the quantity of items with a specific value in Angular 8

I'm attempting to determine the number of objects with a status value of 'Served', which should yield 2. I'm unsure about the method I should use to achieve this. Any suggestions on which method would be best? {full_name: 'Jenny&a ...