Exploring the functionality of promises in JavaScript

Currently, I am using the most recent version of Angular.

The code snippet I've written looks like this:

$q.all({
  a: $q.then(func1, failHandler),
  b: $q.then(func2, failHandler),
  c: $q.then(func3, failHandler),
}).then(func4);

Is it guaranteed that the execution will always be func1, func2, func3, func4?

Because I am experiencing func4 being triggered before the other three functions. This raises another question.

Does $q.then(callbacks).then always ensure that the callbacks are executed before moving on to the next then?

Answer №1

Important Note:

The examples provided below are purely for demonstration purposes and should not be used in a real application. Some of them may even fall under The Deferred anti-pattern. They are meant to showcase how certain functions work.

To address the question at hand, let's conduct some experiments to explore it further.

Given the following callback functions:

function okHandler(value) {
  console.log(value + ' has been called.');
  return value;
}

function doneHandler(values) {
  console.log('Done! : ' + JSON.stringify(values));
}

function delayed(value, delay) {
  var deferred = $q.defer();

  $timeout(function () {
    deferred.resolve(value);
  }, delay);

  return deferred.promise;
}

Parallel Execution:

$q.all({
  a: $q.when('a').then(okHandler),
  b: $q.when('b').then(okHandler),
  c: $q.when('c').then(okHandler),
}).then(doneHandler);

Result:

a has been called.
b has been called.
c has been called.
Done! : {"a":"a","b":"b","c":"c"} 

Parallel Execution with Delay Simulation:

$q.all({
  a: delayed('da', 200).then(okHandler),
  b: delayed('db', 100).then(okHandler),
  c: delayed('dc', 300).then(okHandler),
}).then(doneHandler);

Result:

db has been called.
da has been called.
dc has been called.
Done! : {"b":"db","a":"da","c":"dc"} 

Sequential Execution:

delayed('sa', 400).then(okHandler).then(function () {
  delayed('sb', 100).then(okHandler).then(function () {
    delayed('sc', 10).then(okHandler).then(doneHandler);
  })
});

Result:

sa has been called.
sb has been called.
sc has been called.
Done! : "sc" 

Alternative Sequential Style:

delayed('ssa', 600)
  .then(okHandler)
  .then(delayed.bind(null, 'ssb', 100))
  .then(okHandler)
  .then(delayed.bind(null, 'ssc', 10))
  .then(okHandler)
  .then(doneHandler);

Result:

ssa has been called.
ssb has been called.
ssc has been called.
Done! : "ssc"

Example Plunker: http://plnkr.co/edit/dNZ8koAS4G6fNmahfmj6?p=preview

Now, let's proceed to address your specific queries.

Q: Is the execution order always guaranteed to be func1, func2, func3, func4?

A: No, only func4 is guaranteed to be executed last. The sequence of func1, func2, and func3 can vary.

Q: Does $q.then(callbacks).then always ensure that callbacks are fired before moving to the next then block?

A: Yes!

Answer №2

It's important to differentiate between promises and Q.

Promises are a powerful abstraction that includes a then method.

Consider using $q.defer() and remember to resolve it when needed.

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

Why does ng-pattern run even when the input field is disabled?

Why does angular evaluate a pattern when the input field is disabled? Shouldn't it behave the same way as it does when the input field is hidden? For a demonstration, please refer to this fiddle: Fiddle for reference <div ng-app> <div n ...

Passing variables to each view in Node.js using Express

Currently working on coding a web-based game and looking to share variables across all views. Each user has their own unique race with various variables, such as commodities (money, energy, etc.) and planets (owned, built, etc). The goal is to display th ...

To insert a <div> element within a <tr> element while preserving the exact position of the <tr> tag - here's how you can do it:

I have a challenge with my table where I need to add a green progress bar in the form of a div element within a tr. The width of this progress bar should change dynamically from 0% to 100%, reflecting the current runtime of the video associated with that p ...

Creating a stunning 2D image from a 3D scene through the power of raytracing with webgl and three.js

My goal is to project a 3D scene onto a 2D plane using ray tracing. Although my ultimate aim is volume rendering, I am currently struggling with the basics. I have set up a three.js scene with the viewing plane attached to the camera in front of it. The S ...

Solving synchronization issues when updating and selecting MySql data in a Node.js environment with concurrent multiple requests

Currently, I'm using expressJS with an endpoint that connects to a MYSQL database. This endpoint executes a query to retrieve data and assigns the first result to a user by updating a specific field with the user ID. The rule is that each row can onl ...

Conceal element with ng-pluralize when the value reaches zero

Is there a way to utilize Angular's ng-pluralize to dynamically show or hide an element based on the value being 0, where it should be hidden (ng-hide="value == 0" or ng-if="value != 0")? If the value is 1, the element should display one text, while ...

Mastering Protractor: Implementing browser.sleep within element.all(locator).each(eachFunction)

I am currently expecting the text of each element to be printed one by one, followed by a sleep, and then the next element's text to be printed. However, what is actually happening is that all the texts are being printed first and then a single brows ...

Select2 version 4.0.3 encountering issues when trying to automatically populate additional select2 fields with data fetched through ajax

I'm encountering an issue with Select2. Essentially, I need to populate other form fields with data retrieved from Select2's Ajax search. Even after following an example found here: Select2 4.0 - Push new entry after creation I'm still un ...

Configuring Google Maps API (including charts) for maximum height of 100%

I am having trouble getting my map to display at 100% height using the Google Maps API. I've encountered similar issues in the past with the Google Charts API as well. From what I've gathered, it seems like setting the height of the html and bod ...

Display or conceal a div element depending on the user's choice

I am looking to hide inactive divs, but whenever I reload the page, all tab contents merge into one. The screenshot below shows the issue I'm facing. Screenshot Below is the code snippet: $('.tab a').on('click', function ...

Learning the art of Javascript programming within the HTML5 realm

Seeking assistance with a JavaScript project - I'm attempting to develop a Bubble Buster game reminiscent of pong, but with multiple bubbles. The goal is to have falling bubbles on screen (roughly 100 in total) in various colors dropping from random l ...

Simulated alternate identities for UI Router

I am managing a group of pages/URLs that share a common parent state/template: /orders/list /orders/create /products/list /products/create Currently, I have two dummy states/routes (/products and /orders) that serve as parent states for the other substat ...

What is the reason behind the cross-origin error thrown by JSON.parse?

When I don't use JSON.parse, my code works perfectly fine. However, as soon as I attempt to parse or stringify my data object, a cross-origin error is thrown. Why is this occurring and what steps can I take to resolve it? The snippet of code in Title ...

What could be causing my date to not format correctly as intended?

I have a date stored in my database table that appears like this: "2017-12-07 14:42:38.0611177 +00:00" When I try to format it in my HTML using this code: <td>{{ note.CreatedAt | date : "MMM d, y" }}</td> I anticipate the date to be display ...

How can Next-auth handle redirection for 401 errors?

Currently, I am utilizing Next-auth in combination with rtk query. My goal is to configure the application so that whenever a request results in a 401 unauthorized error, the page will automatically redirect to the login page. How can this be achieved? I ...

Strategies for deploying on production as you develop a fresh Nuxt application

What are some recommended strategies for deploying a Vue/Nuxt project on production, especially for larger applications with lengthy build times? Typically, running the command npm run build Causes the app to be inaccessible to users until the build proc ...

Utilizing Javascript for a Stopwatch/Countdown in the Format: 00:00:00

I am currently working with this block of code: function startStopwatch() { vm.lastTickTime = new Date(); $interval.cancel(vm.timerPromise); vm.timerPromise = $interval(function() { var tickTime = new Date(); ...

Sending the returned value back to the previous view in Ionic

I'm working on creating a form with a unique setup: The main view displays a list of all fields to be filled out, such as 1. Merchant, 2. Amount, 3. Date Instead of a multi-step form, here's what I'm aiming to do: Click on the Merchant f ...

Is it possible to include 'file.php' along with the 'id' using php?

I have constructed my website using php include and the structure of the index is as follows: Menu.php (menu system) main.php (Main page) footer.php (footer section) On the main.php (main page), I have incorporated a news script that utilizes $_GET t ...

Having trouble using a setTimeout() callback to display a Bootstrap Vue modal programmatically

I am currently working on a Vue CLI application (using the Webpack template) that utilizes Bootstrap Vue for displaying modal windows. In my Vue component's mounted() hook, I am attempting to programmatically show the modal by referencing the Bootstra ...