What is the proper way to terminate a Promise.all() in Angular 2?

My current sign-up process involves a Promise.all() being made on every "next" click, resulting in multiple http requests. However, when users quickly click through the process, these requests start to pile up and cause issues with my app.

Is there a way for me to cancel a Promise.all() if a new one is triggered before the previous one has completed? I need a solution to prevent these build-ups of requests causing problems with the functionality of my app.

Answer №1

While promises can be waited on to finish, there is no built-in cancellation feature.

An approach could be to prevent the user from progressing using a disabled next button until all promises are resolved.

<button [disabled]="completed">Next</button>

Answer №2

To enhance the functionality, I would implement observables along with switchMap and debounceTime. Here's a sample approach:

export class MyComponent implements OnInit {
  actions: Observable<any[]>;
  private signals = new Subject<string>();
  constructor() {}

  submit(signal: string): void {
    this.signals.next(signal);
  }

  ngOnInit(): void {
    this.actions = this.signals
      .debounceTime(300)        
      .distinctUntilChanged()
      .switchMap(signal => {
         // Perform HTTP calls based on the signal e.g
         // return this.service.getAction(signal)
      })
      .catch(error => {
        // Handle any errors
      });
  }
}

This logic is inspired by the tutorial at https://angular.io/docs/ts/latest/tutorial/toh-pt6.html#!#-_observable-s

An advantage of using switchMap is that it can cancel ongoing HTTP requests if another signal is received. However, it's important to note that this feature is only beneficial if your server is capable of handling cancelled requests effectively.

Answer №3

When it comes to "canceling a Promise.all()", the idea is to ensure that the promise returned by a Promise.all() does not continue on its success path.

While Promises themselves are not cancelable, there are pattern-based solutions that can achieve a similar effect.

The basic concept behind this approach is fairly straightforward. Essentially, within each batch of promises, you can include a special promise that:

  • will be resolved if the current batch is successful
  • will be rejected once the next batch is initiated

This sets up a sort of competition between different outcomes.

The challenge lies in seamlessly integrating this "super-aggregation" into the final results.

Here is one possible implementation - although it may not be the most concise, there could be more efficient ways to accomplish this task.

function BatchCanceller() {
    // Return a function that takes an array of promises and returns an aggregated promise.
    // Use this returned function similarly to how you would use $q.all().
    var dfrd;
    return function(promises) {
        if(dfrd) {
            dfrd.reject(new Error('cancelled')); // reject previous batch
        }
        dfrd = $q.defer();
        
        // Prepare for all promises to resolve `dfrd` if successful.
        $q.all(promises).then(dfrd.resolve);
        
        // Include `dfrd` in a super-aggregation of promises.
        return $q.all(promises.concat(dfrd.promise)).then(function(results) {
            // If the aggregated promises succeed, remove the last result (from `dfrd`)
            return results.splice(0, results.length-1);
        });
    };
}

var batchCanceller = new BatchCanceller();

var promises = [/* whatever */];
batchCanceller(promises).then(function(results) {
    console.log(results);
}).catch(function(error) {
    console.log(error); // will display "cancelled" if another batchCanceller(promises) is called before the previous one resolves
});

In practical applications, it might be more suitable to implement BatchCanceller() as an Angular factory.

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

What could be causing these Typescript compilation errors I am experiencing?

I am puzzled by the appearance of these errors, especially since I copied the entire ClientApp folder from a running application where they did not exist. https://i.sstatic.net/tcO5S.png Here is the structure of my project: https://i.sstatic.net/P4Ntm.p ...

Tips for updating HTML Ajax content when the back button is clicked

I created a search page with filters that update the URL parameters to prevent values from being lost if the page is refreshed. q = $('#form input[name=q]').val(), srchtype= $('#filter input[name=srchtype]:checked').val(), sortBy ...

How to iterate through the elements of an object within an array using Vue.js and TypeScript

There was an issue with rendering the form due to a TypeError: Cannot read properties of undefined (reading '0'). This error occurred at line 190 in the code for form1.vue. The error is also caught as a promise rejection. Error Occurred <inpu ...

Converting an image to a byte array in JavaScript

Does anyone know how to manipulate binary files in Javascript similar to C? I'm currently facing a critical scenario where I need to create a flipped image. Unfortunately, I don't have access to CSS, canvas, HTML, or the DOM - so I need to accomp ...

Troubleshooting issues with Jquery, Ajax, and PHP integration

Currently, I am in the process of refreshing my knowledge on jQuery and AJAX. In jQuery in 8 hours, there is a code snippet that caught my attention: <!DOCTYPE html> <htmlxmlns="http://www.w3.org/1999/xhtml"> <head> <title>A Sample ...

What did I overlook in my AJAX implementation?

When a user selects a value from the dropdown menu, an Ajax call must be made to the server to retrieve some values in JSON format. Below is the Ajax code //AJAX Security $('#ddlSecurityLevel').change(function () { if ($('#ddlSecurityL ...

Is it possible to assign the margin-bottom property of one element to be equal to the dynamic height of a sibling element?

I am in the process of creating a website that features a fixed (non-sticky) footer placed behind the main content using the z-index property. The footer only becomes visible when the user scrolls to the bottom of the page, achieved by assigning a margin-b ...

Searching by object id from the front-end: A step-by-step guide

Within my collection of meals, there is a specific document I am working with: # Meals collection { name: "burger", tag: ObjectId(63d6bb22972f5f2fa97f1506), } Now, as I navigate through my React application, I find myself needing to send a ...

What is the best way to organize objects based on their keys?

Looking to iterate through object values and append text if the key matches in JavaScript. The object is as follows: { "id": "n27", "name": "Thomas More", "className": "level-1", & ...

The function window.scrollBy seems to be causing a conflict with jjmslideshow, resulting in the page being unable to

I wrote a simple script to create a "smooth scroll" effect when a specific link is clicked: (function() { 'use strict'; // Checking for compatibility if ( 'querySelector' in document && 'addEventListener' in window ...

In JavaScript, promises remain in a pending state

How can I prevent my promises from remaining in the pending state and resolve them instead? var foundPeopleA = findPeopleA().then(function(result) { var res = [] result.map(function(el) { res.push(getProfileXML(el.sid)); ...

What is the best way to eliminate the external pause button?

My website contains the following HTML snippet: <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="a ...

Can you please explain to me how to target a specific element by its ID in the DOM and then move on to the next element with the same ID using jQuery

During the event handling process, a scenario arises where two div elements end up having identical IDs within the DOM structure. While using JQuery, my objective is to specifically target the second occurrence of the div with the aforementioned ID in the ...

Transferring data from a text area to a table with AngularJS

Creating a C# MVC App with AngularJS My goal is to populate a table with values entered in a text area using Angular. Here is the process: Users input values into a text area like this: A B C When a user clicks a button, a modal window should open and ...

The Angular version update is experiencing issues within the Bash command prompt

https://i.stack.imgur.com/2ic0N.png I'm currently using version 6.0.8 of Angular, but when I try to add Angular/PWA to my project, I encounter an error. The command prompt shows my Angular CLI version as 6.0.8, however, in my bash command it displays ...

Object in motion from left to right

For my game, I am planning to introduce obstacles that move from left to right across the <div id="outline"></div>. I have implemented a solution using setInterval(){...} and .animate(), which works well initially. However, after some time, it ...

Switch the displayed image(s) based on the radio button selection made by the user

I need help implementing a feature on my website where users can change an image by selecting radio buttons. For example, there are three options: 1) Fox 2) Cat 3) Dog When the user chooses "Fox," I want an image of a fox to be displayed. If they then sw ...

Is it possible to impose dimensions on a content-editable div?

Is there a way to make a content editable div act like a text box with a fixed horizontal width and unlimited vertical expansion? Take a look at this jsfiddle, and find the code below: http://jsfiddle.net/seoj7cgq/ <!--How do I force the text to stay ...

AngularJS's support for html5mode on GitHub pages is now available

Is it feasible for GitHub pages to accommodate AngularJS in html5mode? I came across a source online suggesting that it can be done with a fallback page for 404 errors. However, this solution seems flawed as it may result in multiple 404 errors, which wou ...

Troubleshooting Javascript Errors in Protractor and WebDriver/Selenium

Recently, I encountered an interesting issue with my Angular site. Upon loading (https://x.y.com/), it immediately redirects to () [just as an example]. Initially, I attempted to resolve this by following the Protractor instructions and running it from the ...