When a sorted array is emitted, it has the tendency to become unsorted again

Although I found a workaround, I'm still intrigued to understand the root cause of this issue. This problem arose while working on a project using Angular 7.

The issue was with sorting an array of objects in a service and then passing that sorted array through a subject to a component. Strangely, the component always received an unsorted array, even though the data was provided from a server via websocket.

In summary, the code structure looked like this:

private sortedData: Data[] = [];
private dataSubject= new BehaviorSubject<Data[]>([]);

// The component subscribes to this observable
public data$ = this.dataSubject.asObservable();

public getData() { // Called from the component class
        this.apiService('command', this.callback)
    }

private callback = (err: any, data: Object[]): void => {
        if (err) {
           // Error handling code (not relevant to the issue)
        } else {
           this.sortedData = data.sort((a,b) => a.order - b.order);
           this.dataSubject.next(this.sortedData); 
        }
    }

I attempted various solutions including:

  • Assigning the value of data to a temporary variable using Object.assign([],data); and manipulating the temp
  • Adding a
    setTimeout(()=> this.dataSubject.next(this.sortedData), 500)
  • Modifying the apiService to return an Observable instead of using a callback
  • Creating my own sorting function
  • Combining all of the above approaches

Despite trying these methods, none of them resolved the issue. When using ng.probe() in the dev console to inspect the array in the service, it was evident that the list remained unsorted.

Interestingly, when I commented out

this.dataSubject.next(this.sortedData);
, the array suddenly became sorted.

To resolve this, I added a getter for the sortedData property and eliminated the use of BehaviorSubject.

While we managed to address this problem, the underlying cause remains a mystery to me.

EDIT

A simplified version of the problematic code can be viewed here. Although I couldn't reproduce our specific issue here, you'll be able to grasp the structure more clearly. The only difference between the example and our application is the utilization of Socket.io within the ApiService.

Even though the problem was resolved, I am keen to uncover what led to this unexpected behavior.

Answer №1

Today, I encountered an issue and took the time to troubleshoot it. In my situation, the component subscribing to the Subject was a table row organizer that was sorting the array in place based on another key (due to its reference).

To resolve this, I decided to emit a copy of the sorted array instead since I needed the original sequence elsewhere.

Perhaps this information will be beneficial to you or someone else experiencing a similar problem. Take a closer look at how the subscriber is manipulating the emitted value and whether the unsorted array is being sorted by a different attribute.

Answer №2

Utilize the sorting logic within the service using rxjs for a more streamlined approach without the need for helper Subjects.

Implement the sorting mechanism inside your getData() method

this.apiService('command', this.callback).pipe(
  map((data) => {
    const sorted = data.sort((a, b) => a.order - b.order)
    return sorted;
  })
);

Then in your component, you can directly subscribe to it or assign it to an Observable variable for rendering in HTML

ngOnInit(): void {
  this.data$ = this.apiService.getData();
  // Use it in HTML: <div *ngFor="let item of (data$ | async)">{{item.order}}</div>

  // Or subscribe to it in the component
  this.apiService.getData().subscribe((data) => {
    this.data = data;
  })
}

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

Find a type that matches a string with any number of arguments separated by commas

Looking for a type that specifically matches strings starting with the prefix func and surrounded by any number of arguments within parentheses. func(1, 2, 3, 4, 5) func(1, 2, 3) func(1, 2, 3, 4, 5, 6, 7) Here is what I have so far: type MyType = `func(${ ...

Having trouble importing a TypeScript module from the global node_modules directory

I have a library folder located in the global node modules directory with a file named index.ts inside the library/src folder //inside index.ts export * from './components/button.component'; Now I am trying to import this into my angular-cli ap ...

How to insert numerous identical elements into an array using Swift

Is there a way to add multiple identical elements to an array without using a loop? Consider an array like this: ["Swan", "Dog"] and you want to change it to: ["Swan", "Dog", "Cat", "Cat", "Cat", "Cat", "Cat", "Cat", "Cat", "Cat", "Cat", "Cat"] (addin ...

Having difficulty with defining a local array and properly passing arguments to various methods

My task was to create a Java class that generates an array of integers, populates it with values, showcases the unsorted values, organizes the values in ascending order, and displays the sorted values. Overall, I have accomplished most of this task succes ...

Implementing the inheritance of variables from a subclass to fill an array based on user input: a step-by-step guide

I am currently working on an assignment for my Java class that involves making Shapes comparable by adding "implements Comparable" and creating the method: public int compareTo(Object o) in the abstract class Shape. For the comparison, we are supposed to ...

Troubleshooting problem with displaying Font-awesome icons in Angular4 and Bootstrap4

Utilizing bootstrap4 to showcase the user icon on the signup page worked perfectly with @angular/cli v1.3.x. However, after upgrading to version @angular/cli v1.6.6, I encountered an issue. Below is the warning message that appears when running: ng serv ...

What is the best way to configure Winston with Webpack?

I'm working on an electron application that utilizes node.js and I want to integrate the Winston logging library. After adding Winston to my package.json file, I encountered warnings from the colors.js dependency when running the webpack build command ...

Angular Fails to Identify Chart.js Plugin as an Options Attribute

Encountering issues with using the 'dragData' plugin in Chart.js 2.9.3 within an Angular environment: https://github.com/chrispahm/chartjs-plugin-dragdata After importing the plugin: chartjs-plugin-dragdata, I added dragdata to the options as sh ...

Angular: Design dependent on attributes

Can I customize the styling of a div in accordance with a boolean property called "isActive" on my controller using Angular? <div class="col-md-3" (click)="isActive = !isActive"> <div class="center"> <i class="fa fa-calendar"& ...

Incorporate a service into a base class in Angular2 to ensure its functionality extends to all derived classes

I have multiple classes with a hierarchical inheritance structure as follows: class A (an abstract class) class B extends A class C extends B I am looking to incorporate a service into class A to enable a function that utilizes notifications. How can I ...

Comparing casting to pointer to array in C and C++ (or GCC and G++)

When compiled as c code (using gcc with the file suffix '.c'), the following code compiles and works as expected. However, an error is thrown when compiled as c++ code (using g++ or gcc with the file suffix '.cpp'): int sum_square_matr ...

Using arrays in MySQL query through PHP

Hey everyone, I am relatively new to PHP but I am eager to learn. Recently, there has been a change in the requirements for my project. The values B1 to B11 are no longer fixed and can range from B1 to B6 or even up to B50. I understand that I may need a ...

Why is the value always left unused?

I am having an issue with handling value changes on focus and blur events in my input field. Here is the code snippet: <input v-model="totalAmount" @focus="hideSymbol(totalAmount)" @blur="showSymbol(totalAmount)" /> ...

Ensure that Template.fromStack() includes resources with the specified logical identifiers

Currently, I am overhauling a CDK stack in TypeScript that has reached the resource limit. Given that it includes stateful resources, I need to ensure that the revamped stack points to the same resources and not new ones that could lead to unfavorable resu ...

The topic at hand pertains to a specific exercise featured in the well-known book Eloquent JavaScript

In this exercise, the final step is to create a recursive function that takes a joined list and an index as parameters. The function's purpose is to find the value in the object within the list at the specified index. The code I have written seems to ...

Type Assertion for Optional Values in TypeScript

Just confirming the proper way to handle situations like this. My current setup involves using Vue front-end with Typescript, sending data to an API via axios. I've defined reactive objects as follows: const payload = reactive({ name: '' ...

The specified property is not present in the type '{}'

I've been incorporating Typescript into my React application Within my mapStateToProps, this is the code I'm using const mapStateToProps = (state: AppState) => { console.log(state) return { ...state.player, position: ...

Establish a trial Firestore database for testing purposes

Seeking guidance on how to effectively manage a test database with Firestore while also highlighting key aspects of my current app's implementation. Currently, I have a production database set up for my Ionic 3 app. I am utilizing one production d ...

What is the correct method for retrieving data from response._body?

Initially, my nodejs server is sending the following response: "["name1","name2","name3"]" However, in my angular 2 service code, I have the following: return this.http.get(this.config.apiUrl + '/folder').map((response:Response)=> { ...

Steps for transforming a dataframe into a 3-dimensional ndarray

Is there a way to convert a Pandas dataframe into a 3D numpy array? I attempted to use df = df.to_numpy(). However, this only produces a 2D matrix. The original dataframe is structured as follows: days 0 1 2 3 4 5 6 7 ...