RxJS and asynchronous operations - Mastering the flow of execution

Exploring the concepts of async with RxJS is my current goal; I created this example to dive into how async function calls interact within RxJS observables. The outcome looks like this:
func1 --- 10
func1 --- 20
func1 --- 40
func1 --- 30
switchMap ---1--- -->item: 0
switchMap ---1--- -->item: 1
switchMap ---1--- -->item: 2
switchMap ---1--- -->item: 3
switchMap ---1--- -->item: 4
switchMap ---1--- -->item: 5
switchMap ---1--- -->item: 6
switchMap ---1--- -->item: 7
END
switchMap ---2--- -->item: 1
switchMap ---3--- -->item: 0.111
switchMap ---3--- -->item: 1.111
switchMap ---3--- -->item: 2.111
switchMap ---3--- -->item: 3.111
switchMap ---3--- -->item: 4.111
switchMap ---3--- -->item: 5.111
switchMap ---3--- -->item: 6.111
switchMap ---3--- -->item: 7.111
switchMap ---3--- -->item: 8.111
switchMap ---3--- -->item: 9.111
MERGEMAP: item-->1000
MERGEMAP: item-->2000
N E X T --> 1000
N E X T --> 2000
MERGEMAP: item-->3000
MERGEMAP: item-->4000
N E X T --> 3000
N E X T --> 4000
MERGEMAP: item-->5000
N E X T --> 5000
C O M P L E T E
I'm puzzled by why func1 --- 40 appears before func1 --- 30 and wondering why END shows up amidst switchMap ---1--- and switchMap ---2---
Would appreciate any insights.

import { bufferCount, from, mergeMap, Observable, switchMap } from "rxjs";

module async1 {
  async function func1() {
    console.log("func1 --- 10");
    const loop0 = async () => {
      return from([0, 1, 2, 3, 4, 5, 6, 7]);
    };

    const loop1 = async () => {
      return 1;
    };

    const loop2 = async () => {
      const arrayLoop2 = [];
      for (let i = 0; i < 10; i++) {
        arrayLoop2.push(i + 0.111);
      }
      return arrayLoop2;
    };

    const loop3 = async () => {
      const arrayLoop3 = [1000, 2000, 3000, 4000, 5000];
      return from(arrayLoop3);
    };

    let myObservable: Observable<number>;

    console.log("func1 --- 20");
    loop0().then((value) => {
      myObservable = value;
      const myPipeline = myObservable!.pipe(
        switchMap((item) => {
          console.log(`switchMap ---1--- -->item: ${item}`);
          const loop1Result = from(loop1());
          return loop1Result;
        }),
        switchMap((item) => {
          console.log(`switchMap ---2--- -->item: ${item}`);
          const loop2Result = loop2();
          return loop2Result;
        }),
        switchMap((items) => {
          items.forEach((item) => {
            console.log(`switchMap ---3--- -->item: ${item}`);
          });
          const loop3Result = loop3();
          return loop3Result;
        }),
        switchMap((item) => {
          return item;
        }),
        bufferCount(2),
        mergeMap((items) => {
          items.forEach((item) => {
            console.log(`MERGEMAP: item-->${item}`);
          });
          return items;
        }, 3)
      );

      console.log("func1 --- 30");

      const mySubscription = myPipeline.subscribe({
        next: (item) => {
          console.log(`N E X T --> ${item}`);
        },
        error: () => {
          console.log(`E R R O R`);
        },
        complete: () => {
          console.log(`C O M P L E T E`);
          mySubscription.unsubscribe();
        },
      });
    });
    console.log("func1 --- 40");
    return true;
  }

  func1().then((resolve) => {
    console.log("***END***");
  });
}

Answer №1

It’s important to note that when dealing with code related to observables, you don’t have full control over when it will be executed. If you need to ensure that all the logic within func1() is completed before moving on to the next function, it’s best to avoid using observables and subscriptions inside func1(). Instead, consider using Promise<Type> along with await. This way, you can call func1 like this:

await func1();

If your goal is to run functions console.log("func1 --- 40") and console.log("***END***") after the RxJS work is finished, make sure to include them within the body of complete:

        complete: () => {
          console.log("func1 --- 40")
          console.log(`C O M P L E T E`);
          console.log("***END***")
          mySubscription.unsubscribe();
        }

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

Tips for preventing conflicts between variables and functions in JavaScript (no need for a jQuery plugin)

How can I prevent variable and function conflicts in Javascript without relying on jQuery plugins? I am interested in creating my own functions but want to avoid conflicts. I believe using function scope, where functions are used solely for the purpose of ...

Bind a tree structure in Knockout by linking parent IDs to the primary key column

I want to organize data returned from a stored procedure into a tree structure using the guidance provided in the Knockout documentation. The data I am working with has the following format: ID | Name | ParentID 1 | Parent 1 ...

Choosing the right target for AngularJS/Node.js output

I'm working on a project that utilizes AngularJS and node.js to process CSV files before generating an output. Right now, the only method I have for outputting the file is through: <a download="fileName.csv" ng-href="{{file}}">fileName.csv</ ...

When clicking the next or previous button in VueJS, showcase a list

I am looking to create a case management system in a JavaScript view. The system will track employees arriving and leaving a department, returning 3 objects (entries and exits) for the current week, next week, and the week after that. By default, the syste ...

AngularJS experiencing issues with Bootstrap multiselect functionality

I am currently integrating bootstrap-multiselect into my AngularJS application. To do this, I've included the following scripts in my master page (index.html). <script src="/bower_components/jquery/dist/jquery.min.js"></script> <scrip ...

Only users who are logged in to Node.js can access the message

Whenever users are online and do not close our clients like a browser tab or android application, I have the ability to send a message to each specific user by utilizing the following code: socket.broadcast.to(socketId) .emit('new message', ...

Tips for closing the stdio pipes of child processes in node.js?

Looking to spawn a child process from node.js and monitor its stdout before closing the pipe to terminate the node process. Here's my base code snippet that is currently not ending the node process: const childProcess = require("child_process"); con ...

How can you convert an epoch datetime value from a textbox into a human-readable 24-hour date format

I have an initial textbox that displays an epoch datetime stamp. Since this format is not easily readable by humans, I made it hidden and readonly. Now, I want to take the epoch value from the first textbox and convert it into a 24-hour human-readable da ...

Error: Attempting to assign a value to the 'firstData' property of an object that is undefined

I am encountering two identical errors in my service. Below are the details of my service and controller: Service code snippet: getData: function (dataRecievedCallback, schemeid, userid) { //Average JSON api averageData = functi ...

Exploring methods to successfully upload a blob to Firebase and modify it using cloud functions

For days now, I've been attempting to successfully upload a file to firestorage using firebase functions but haven't had any luck. This is the progress I've made so far: export const tester = functions.https.onRequest(async (request, respons ...

The Skeleton-Avatar and ImageButton components in MUI React have had their backgrounds reshaped into perfect ovals

I am facing an issue with the mui Stack where all the background shapes of the Skeleton Avatar and background area are turning into oval or ellipsoid shapes. I have tried setting equal width and height for Avatar but it has not solved the problem. Is ther ...

Having trouble with Gulp JS and CSS minification where existing minified files cannot be replaced

I've hit a roadblock in trying to resolve my search and google issue. My current challenge involves Gulp and cssmin. I can't seem to pinpoint the cause of an error. My aim is to have both the original CSS files and their minified versions in the ...

Retrieve information from the selected row within a table by pressing the Enter key

I have a search box that dynamically populates a table. I am using arrow keys to navigate through the rows in the table. When I press the enter key, I want to retrieve the data from the selected row. For example, in the code snippet below, I am trying to ...

Potential dangers involved in sending HTML content through an AJAX request over a secure HTTPS connection

I am exploring the idea of dynamically loading HTML content, such as updating a Bootstrap modal dialog's contents using AJAX calls instead of refreshing the entire page. However, before I proceed, I want to understand the potential risks involved and ...

Saving the object returned by the useRef hook into the Redux state

I have a question. I am developing a music platform similar to Spotify using Next.js. To manage states, I am utilizing Redux Toolkit. In order to play music, I have integrated the audio element within a component that includes controls to adjust the music ...

How can I utilize the Redux store outside of a component in a React application with ASP.NET Core and TypeScript?

While I have some experience with React, I am new to using Redux. Luckily, Visual Studio 2017 comes with a built-in template for React + Redux under .NET Core 2.0. About my environment: Visual Studio 2017 React 15.6.1 TypeScript 2.4.1 Redux 3.7.1 Rea ...

Is it possible to use TypeScript in a React Native project with a JavaScript file?

Currently, I am learning React Native by working on app clones like Instagram and YouTube. I have recently started an AirBnb clone project, but I'm facing some issues with the initial build. One issue I noticed is that in 'App.js', the temp ...

Switch to a different element by rolling over one

I need assistance with a menu setup where the submenus are located in separate divs on the page. Both the parent elements and submenus have numerical identifying IDs, and I am struggling to create a rollover effect that would automatically open the corresp ...

Typescript Imports Simplified for Snowpack

I am working with Snowpack and trying to import a Typescript package from Github packages using the following code: import SomeClass from '@myRepo/lib' However, I keep getting an error message saying: "/_snowpack/pkg/@myRepo.SomeClass.ts&qu ...

"Converting a Service Worker from JavaScript to TypeScript: A Step-by-Step

Scenario I am in the process of converting my service-worker file from JavaScript to TypeScript in order to improve maintenance. Below is a snippet from my sw.js file: /* eslint-disable no-console */ self.addEventListener("push", (event) => { ... }); ...