Observing rxjs Observable - loop through the results and exit when a certain condition is met / encountering an issue with reading property 'subscribe' of an undefined value

I'm fairly new to working with rxjs and I've been struggling to find the right operator for what I want to achieve.

Here's my scenario - I have an array that needs to be populated with results from another observable. Once this array has enough data, obtained through subscribe calls, I would like to stop the process and return the complete array.

// Just to give you some context, there's a class variable named keys

    result = getResults(data, index).subscribe((result: any[]) => { 
          doSomethingWith(result);
    });

    getResults(data: any[], index: number) : Observable<any[]> {
       obsFunctionThatGetsMeData(keys[index]).subscribe(result => {

         data = data.concat(result);

          if(data.length >= NEEDED_NUM_DATA) {
              return Observable.of(data);

          } else {

            /* need to call obsFunctionThatGetsMeData(keys[index++]) and follow the same logic as above. */

          }
       );
    }

I understand that nesting subscribes is not recommended, but this gives you an idea of my requirements. I've looked at takeWhile, which works based on a condition, but I haven't figured out how to make additional calls if that condition fails. Does anyone have suggestions for an operator that fits this use case?

Thank you!

  • obsFunctionThatGetsMeData returns Observable

Update: Found a solution by using recursion & switchmap

getResults(data: any[], index: number): Observable<any> {
   return obsFunctionThatGetsMeData(keys[index]).pipe(
        switchMap(result => {
            if (result) {
                data = data.concat(result);

                if (data.length < NEEDED_NUM_DATA && index < keys.length) {
                    return getResults(data, ++index);
                } else {
                    return Observable.of(data);
                }
            }
        }));
}

Answer №1

While I may not be an RxJS expert, it's my understanding that a solution along these lines could potentially work:

Rx.Observable.from(callFunctionToRetrieveData)
  .take(NUMBER_OF_DATA_NEEDED)
  .subscribe(handleData);

public take(count: number): Observable Emits only a specific number of values from the source Observable.

This is just a concept to ponder over and should not be considered a definitive answer.

Answer №2

It seems like obsFunctionThatGetsMeData behaves similar to an HTTP request by emitting once, and you aim to gather results from a total of NEEDED_NUM_DATA requests into an array while also appending them to the existing data parameter.

You can attempt the following approach:

collectData( currentData: any[], startingIndex: number ): Observable<any[]>
{
    return Observable.range( startingIndex, NEEDED_NUM_DATA )
        .concatMap( i => obsFunctionThatGetsMeData( keys[i] ) )
        .reduce(( accumulator: any[], value ) => accumulator.concat( value ), currentData );
}

Answer №3

Utilizing promises is key in this scenario (primarily due to dealing with individual values).

Despite appearances of working with a stream of outcomes (the observables), the truth is you are processing one value at a time. Each value undergoes independent operations within a loop that stores the result into an array. This results in NEEDED_NUM_DATA distinct variables being consolidated into a collection.

This approach makes it significantly simpler to comprehend and achieve your objective:

var NEEDED_NUM_DATA = 4;
var collection = [];
async function fetchResults() {
  let url = 'https://jsonplaceholder.typicode.com/posts/';
  let i = 1;
  while(collection.length <= NEEDED_NUM_DATA) {
    let result = await fetchesData(url + i++);
    collection.push(result);
  }
}
async function fetchesData(url) {
  const response = await fetch(url);
  const json = await response.json();
  return json;
}
fetchResults()
.then(()=>console.log(collection));

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

Using ng-repeat and selectize in AngularJS to populate a multi-select drop-down with values and set selected values

In this instance, I was able to achieve pure HTML select multiple functionality by using this example (JS Bin of pure html select tag). However, instead of sticking to just the pure HTML approach, I opted to use the Selectize plugin. The confusion arose w ...

Refresh gif without having to reload it in Internet Explorer 11

I'm attempting to create a feature where a gif restarts when clicked by the user, without needing to reload it (due to the heavy size of the gif which is preloaded for my application). The current code functions flawlessly on Chrome and other "modern ...

What steps should I take to handle an ArrayIndex out of bound error in JavaScript?

Consider the following array: var john = ['asas','gggg','ggg']; If an attempt is made to access john at index 3, i.e. john[3], it results in an error. Is there a way to show a message or trigger an alert indicating that ther ...

Record the cumulative amount computed using an asynchronous callback

If I use code similar to the one below, I am able to obtain the total byte size value every time a file is added. How can I log out only the total files size after it has been calculated in the fs.stat callback? var fs = require('fs'); var to ...

Issue: Assertion violation: The use of <Link> element is restricted to within a <Router>. Any solutions or suggestions?

In my React and Next Js application, I am utilizing react-router-dom for routing purposes. The dependencies listed in the package.json file are as follows: This is how my current package.json file looks: { "name": "MUSIC", "versio ...

Isotope data-filter not working properly following an Ajax callback

I'm looking for a way to create a filter that can be dynamically updated: I have utilized the isotope javascript library in an external script file: var $container = $('.isotope'); // initialize isotope $container.isotope({ ...

Transfering data to Handlebars while rendering a template

Is there a method to pass a variable to a handlebars template during its rendering process? Below is the template in question: <script id="listingTopics" type="text/x-handlebars-template"> {{#each this}} <div class="wrapper_individual_listing ...

Angular - obtain a secure reference to a lazily loaded DOM element

In my project, I have a specific template section that should only be present in the DOM when its corresponding object exists. In addition to this requirement, I need to access the form reference and attach an Observable using fromEvent('change') ...

Show various attachment file names using jQuery

Utilizing jQuery, I've implemented a script to extract the filename from a hidden field and then append it to the filename class in my HTML. filenameCache = $('#example-marketing-material-file-cache').val().replace(/^.*[\\\/ ...

Strategies for implementing classes in Typescript

I've been working on incorporating more classes into my project, and I recently created an interface and class for a model: export interface IIndexClient { id?: number; name?: string; user_id?: number; location_id?: number; mindbody_id?: nu ...

Transform an array of object's designated key values into a string that is separated by commas

Is there a way to convert specific key values of an object into a comma-separated string? I have been able to do this with arrays, but my current challenge is that my data is an array of objects. I want to convert each 'id' value into an array of ...

Difficulty updating Material UI table

Currently in the process of updating my react site to version 16.8, I have encountered an issue with a material ui table. The functionality involves users selecting certain options, triggering a rest call when a button is clicked, and then displaying the r ...

Tips to prevent browser from freezing while creating a large number of HTML elements

I am currently utilizing Selection.js to develop a customizable grid on my website. To make this work effectively, I need a specific number of div elements to establish the selectable area. In my scenario, I generate all the divs using a for loop and then ...

The information within the ajax request remains static

I made changes to my ajax data, saved it and even double-checked the file location. However, the old version is still appearing as if it's cached. Here is the original code: function setMessages(roomId, username, message){ $.ajax({ type: ...

The AngularJS directive seems to be having trouble receiving the data being passed through its scope

Check out this HTML code snippet I created: <div ng-controller="ctrl"> <custom-tag title = "name" body = "content"> </custom-tag> </div> Take a look at the controller and directive implementation below: var mod = angular.mod ...

Troubleshooting issues with AJAX script and JSON formatted data

Here is my complete script: <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/E ...

Delete element from the array upon removal from the AutoComplete component

I am facing a challenge with the Material UI AutoComplete component in my project. The issue arises when I try to update the state of the associateList after clearing a TextField. Additionally, I would appreciate any guidance on how to handle removing an ...

Facing issue in Visual Studio 2015 with Angular 2 @component not able to resolve the signature of the class decorator

Trying to define a decorator on top of my class in Visual Studio 2015 is causing an error during the build process. The specific error message states: "Build: Unable to resolve signature of class decorator when called as an expression." import { Component ...

Creating a task management application using AXIOS and VUE for easy data manipulation

I am currently working on a small app to enhance my skills in VUE and Axios. However, I am facing a roadblock when it comes to the update functionality. I am struggling to pass the ID to the form for updating and despite watching numerous tutorial videos ...

ng-include not functioning properly within ng-table

In the table, there is a data structure <tr ng-repeat="question in $data" ng-include="'/views/partials/questionList.html'"></tr> Within the questionList.html file: <td class="top-td" data-title="'ID'" sortable="&ap ...