AngularJS : "Executing successive promises" with additional functions interspersed

Recently, I encountered a challenge in my Angular project. As a newcomer to Angular, I was tasked with modifying a directive that handles forms to ensure the submit button is disabled during processing and then enabled again once all operations are complete.

Given that the functions being invoked often involve asynchronous calls, a simple sequential approach did not suffice.

In an attempt to address this issue, I initially implemented the following code snippet:
var ngSubmit = function() {
  vm.disabled = true;
  $scope.ngSubmitFunction();
  vm.disabled = false;
}

However, the submit button became enabled before the async calls within `ngSubmitFunction()` had finished.

Upon further consideration, I sought to incorporate promises into the solution, resulting in the following implementation:

var promise = function() {
  return $q(function (resolve) {$scope.ngSubmitFunction()});
}
var ngSubmit = function() {
  vm.disabled = true;
  promise().then(function() {
   vm.disabled = false;
  });
}

Regrettably, while this modification did not throw any errors, the button remained disabled as the `.then` function was never executed.

I experimented with different approaches for defining promises, yet encountered identical outcomes, except for one particular method:

$scope.submitPromise = function() {
  return $q.when($scope.ngSubmitFunction());
}

Although this version did trigger the `.then` function, it still failed to wait for child async functions to complete. The `.then` function seemed to execute instantaneously, much like the original sequential logic.

Considering the unpredictable nature of `ngSubmitFunction()`—which could potentially encompass multiple asynchronous operations—I found myself contemplating alternative strategies. Specifically, how can I effectively chain promises in scenarios involving non-promise functions? Is there a method to ensure certain code executes only after all other processes have concluded?

Within `ngSubmitFunction()`, the flow typically involves:

- Invocation of `func()`

-- Evaluation within `func()` to determine whether to call `create()` or `update()`

-- -- Execution of `update()`, which includes an asynchronous call to `elementFactory.update()`

-- -- -- Triggers `elementFactory.update().then(function())` upon completion

-- -- -- -- It's at this precise juncture that the button should be re-enabled.

How can I achieve this synchronization? Is there a viable approach to integrating events from DataFactory when individual async calls terminate? This scenario raises complications if `update()` initiates multiple asynchronous requests concurrently.

Answer №1

When incorporating promises into your code, it's important to ensure that your async functions are structured to return promises. Here is an example of how this should be implemented:

const submitAction = function() {
  form.disabled = true;
  $scope.submitFunction().then(() => {
      form.disabled = false;
  });
}

Answer №2

I'm not sure what lies beneath the surface of ngSubmitFunction()

If you're hoping for promises to come to your rescue, think again. Promises or $q.when aren't magical enough to peek into the function call and determine the asynchronous operations it initiated or wait for them - ngSubmitFunction() must itself return a promise for its asynchronous outcomes.

Every function in your codebase that performs anything asynchronous which needs to be awaitable must return a promise. There's no way around this requirement.

Answer №3

Just a quick update for those curious minds out there - we're still grappling with finding a solution, but it seems like there may not be one on the horizon. Our current plan is to add returns throughout the chain of functions to ensure that the ngSubmitFunction receives a promise and can wait for it to complete before moving on to '.then'. This approach not only covers scenarios where there's a single promise involved, but also aligns with solid programming principles.

Cases involving multiple promises are few and far between, so we'll handle them manually within the controller.

A big thank you to everyone who has shared their thoughts and comments on this matter.

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

I am experiencing issues with the HTTPClient call not returning accurate JSON data within my Appcelerator Titanium application

Every time I attempt to retrieve information from a JSON file, I encounter an error. function search(e){ var url = 'https://www.dotscancun.com/createjson.php?id=100001'; var xhr = Ti.Network.HTTPClient({ onerror: function(e){ ...

Utilizing URL Parameters in MEANJS

I'm currently testing my app on localhost:3000/#!/, and am encountering difficulties in retrieving URL parameters for use with Express. I have set up a new server routing file that includes the following: admin.server.routes.js 'use strict&apos ...

"Transforming Selections in Illustrator through Scripting: A Step-by-Step Guide

In Illustrator, I successfully used an ExtendScript Toolkit JavaScript code to select multiple elements like text, paths, and symbols across different layers. Now, I am looking to resize them uniformly and then reposition them together. While I can apply ...

Bringing in a legacy ES5 module for integration within a ReactJS component

Attempting to incorporate an ES5 module into a new ReactJS application has been quite the challenge. I'm struggling with understanding the correct way to import the module so that the main function within it can be accessed and executed. Currently, m ...

Are you experiencing difficulty loading ng-view in AngularJs?

I am new to AngularJs. I am currently using a wamp server and have successfully loaded the HTML page, but unfortunately the view is not being displayed. I have added ng-app to the body as well, but still unable to load the view. <!DOCTYPE html> ...

What is the best way to leverage command line arguments with AngularJS Protractor?

Currently, I am utilizing Protractor for executing extensive end-to-end tests. Instead of storing login credentials in a spec file, I am keen on passing them through the command line. Upon stumbling across a post showcasing the usage of process.argv.forEac ...

What is the best way to divide two ranges that are intersecting?

Seeking a method to divide two overlapping ranges when they intersect. This is my current progress using typescript, type Range = { start: number; end: number; }; function splitOverlap(a: Range, b: Range): Range[][] { let result = []; const inters ...

What steps can be taken to extend the duration that the HTML necessary validation message is displayed?

Is it possible to extend the duration in which the HTML required validation message is displayed? Currently, it seems to appear for too short a time. ...

Retrieve a Google map using Ajax in a PHP script

I'm attempting to display a google map on my homepage using the following function: function addressCode(id, concatenatedToShowInMap) { var geocoder; var map; geocoder = new google.maps.Geocoder(); ...

Model updating with the addition of an item and triggering a secondary ng-repeat for refreshing

As I was working on the phone tutorial, I found myself pondering how to implement a specific use case. The browser renders a list of phones. When the user clicks on add phone for one of these phones, the function addItem is triggered and adds that phone ...

`Generating an ever-changing masonry layout on a website using live data`

I'm currently working on a new web project and I want to incorporate a masonry view for the images on the homepage. The plan is to host this project on Azure, using blob storage for all the images. My idea is to organize the images for the masonry vi ...

Enhancing the building matrix with JavaScript (or jQuery)

I have created a custom Javascript function for extracting specific data from a matrix. The main purpose of the function is to retrieve data based on dates within a given range. Here's how it works: The matrix[0][i] stores date values I need to extr ...

Receive updates from the backend GraphQL and display them on the frontend React application while executing a mutation

I recently implemented a mutation call from the frontend (react) to the backend, running 5 SQL query files. While the backend processes the queries, the frontend simply shows a "loading..." message. //frontend <Button onClick={()=>addData()} /> C ...

What are the pros and cons of using a piped connection for Puppeteer instead of a websocket?

When it comes to connecting Puppeteer to the browser, you have two options: using a websocket (default) or a pipe. puppeteer.launch({ pipe: true }); What distinguishes these approaches? What are the benefits and drawbacks of each method? How do I know wh ...

Encountering errors with passport-google-oauth20: InternalOAuthError arises when fetching user profile fails and attempting to set headers after they have already been sent to the client

When using passport strategies for various social media logins, I encountered the following two errors: InternalOAuthError: Failed to fetch user profile Cannot set headers after they are sent to the client I suspect that I may have returned a callback or ...

What is the process of integrating an EJS file into the app.js file?

Within my index.ejs file, I have included a script tag containing JavaScript for DOM manipulation. Now, I am looking to access a variable declared within this file from my app.js file. How can I make this happen? When referencing a variable in an ejs file ...

Making numerous changes to a single field in mongoDB can result in the error message: "Attempting to edit the path 'X' will generate a conflict at 'X'."

Looking to streamline my update operation: private async handleModifiedCategoryImages(data: ModifiedFilesEventData) { this.categoryModel .findByIdAndUpdate(data.resourceId, { $pullAll: { images: data.removedFiles || [] } ...

Can default query parameters be predefined for a resource in AngularJS?

When working with a simple resource like the one defined below, it is possible to utilize the Receipt.query() method to retrieve a collection from the server. In addition, by calling Receipt.query({freightBill: 123}), a query parameter such as freightBill ...

Error message "Property 'name' does not exist on type '{}'" is encountered when using Ionic/Angular HttpClient and no data type is specified

While working on my Ionic project, I encountered an error in Angular when trying to fetch data from an API using HttpClient. The error message that popped up was 'Property 'name' does not exist on type '{}'.'. Below is the cod ...

Issues arise when trying to integrate external JavaScript files into a Vue application

I am facing an issue with including external JS files in my HTML document. The website requires these files to function properly. What I have attempted: In the main.js file, I tried adding these imports: import '../../assets/js/jquery-3.5.1.min&apos ...