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

Creating a hover effect for displaying image masks

My website features a profile page displaying the user's photo. I am attempting to create a functionality where when the user hovers over their photo, a transparent mask with text appears allowing them to update their profile picture via a modal. How ...

Incorporating <span> elements into a comma-separated list using Jquery on every other item

When I receive a comma-separated list of items from a database and insert them into a table cell, I want to apply alternating styles to make it easier for users to distinguish between them. For example: foo, bar, mon, key, base, ball I'm looking to ...

The necessary String parameter 'licenceplate' is missing

After searching through various existing questions related to my issue, I have not been able to find a solution. The @RequestBody method mentioned in this question and this one did not work for me. The problem I am facing involves passing parameters from ...

Learn how to dynamically disable a button using jQuery within the Materialize CSS framework

While attempting to disable a button in Materialize CSS using jQuery, I encountered an issue. Despite following the documentation found here, it seems that simply adding the 'disabled' class does not automatically disable the button as expected. ...

Tips for implementing the quill-image-drop-module with Vue 3

I am currently utilizing the vueup/vue-quill package for Vue 3 and I would like to incorporate the kensnyder/quill-image-drop-module. This is the snippet of my code: Main.js import { QuillEditor } from '@vueup/vue-quill'; import '@vueup/vu ...

What is the best method for ensuring that cheese rises to the top?

Is there a way to increase the value of the variable cheese? I suspect it has something to do with how the variable cheese is defined each time the JavaScript is activated, but I'm not sure how to go about it. Can you offer some guidance on this? & ...

Changing text array to field identifiers with JavaScript

Is there an elegant way in ECMAScript 6 to transform a string array generated from a map function into field names within a dynamically created object? For instance, if I receive the following output from my map function: ["checkbox1Value", "checkbox4Val ...

Display personalized error messages using jQuery and PHP

I implemented an Ajax autocomplete feature on an input field within a form using jQuery. Here are the ajax settings I have set up: $.ajax({ type: "POST", url: myUrl, data: $("#id__form").serialize(), success: function(data){ ...

Submit form in a new tab and refresh the current page

It seems like my mind is hitting a roadblock, I'm having trouble finding a better solution for this particular issue: I need to send a form via POST method (with data handling on the server) and have it open in a new tab with a custom URL containing ...

CKeditor does not accept special characters or diacritics in keywords

Recently, I came across a helpful code snippet for CKeditor that counts and ranks the most used words in a textarea. This feature is invaluable for generating SEO-keywords suggestions while writing articles. However, there is an issue with non-English char ...

Error: Unable to locate module '@/components/Header' in Next.js project

I'm currently facing an issue while working on my Next.js project. The problem arises when I attempt to import a component into my 'page.js' file. In the 'src' folder, I have a subdirectory named 'components' which contai ...

The step-by-step guide on displaying API choices in an Autocomplete feature and keeping them up

Having trouble with updating autocomplete options. An error message pops up in the console log when I try to deselect a tag or select a new one: MUI: The value provided to Autocomplete is invalid. None of the options match with [{"catName":{&qu ...

What is the best way to toggle DOM classes in React using Material-UI components?

Currently utilizing Material UI alongside React, I have a div element: <div className={classes.div}></div> I am attempting to dynamically add a conditional class to it: <div className={classes.div + divActive ? `${classes.div}__active` : &a ...

angular-in-memory-web-api encounters a 404 error

I recently completed the heroes tour and now I am trying to work on something similar, but I seem to be having trouble understanding angular-in-memory-web-api. Here is a snippet of my code: clients-data.service.ts import { Injectable } from '@angular/ ...

Tips for transferring a jQuery array to PHP

I am encountering an issue when trying to send a jQuery array to PHP. Initially, I have one form in HTML and upon clicking 'add', I end up with two forms. Afterwards, I input data into the form which is then stored in a jQuery array. However, I a ...

Is it possible to include an if/else statement within a tailwind class in React components?

I want to dynamically change the background color of a div based on a condition. If the condition is true, I want the background color to be white; otherwise, I want it to be black. Despite trying to achieve this using an if/else statement, the background ...

What is the browser location for storing JavaScript constants?

How can I retrieve the value of a constant using a string as its name, where the constant is an arrow function? const foo = (bar) => { return bar } I tried accessing it through the window object but got undefined: let fn = window['foo'] // ...

Is there a way to track and detect alterations to an element using JavaScript or jQuery

Can I detect the addition of a specific CSS class to an element without having to create a new event? ...

How can I use Ajax code to send data to a PHP page and receive the results as a JSON-encoded multidimensional array containing information on each item?

Apologies for the unconventional question title. What I am trying to accomplish is managing two tables in my database: a hotel table (table1) and a room type table (table2). My goal is to allow customers to customize their travel packages by changing hote ...

Conceal a list of items within a div that has a particular class

This is a sample of my HTML code: <div class="row"> <div class="col-md-12"> <div class="scrollbox list"> <ul class="list-unstyled"> <li id="articulate.flute">articulate flut ...