Is Angular's promise implementation asynchronous in nature?

I can't seem to figure out the behavior of Angular's promises. Are promises actually asynchronous? I'm a bit confused about this concept.

When using promises in my code to handle a large process (such as reading and writing hundreds of big files), I noticed that the display seems to freeze, even though the code is wrapped inside a promise. This makes me think that it might not actually be asynchronous and could be blocking the main thread.

In the snippet below, which you can also view on this Plnkr, I am troubled by how to update the progress bar while the big process is running. I understand why the display freezes when the process is executed in the main thread, but I don't see why it's still freezing when using Angular's promises.

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, $q) {
  
  function hugeProcess () {
    var i = 0;
    var start = new Date().getTime();
    while (i++ < 100000) {
      console.log(i);
    }
    var end = new Date().getTime();
      var time = end - start;
      $scope.processTime = 'Done in ' + time  + 'ms';
  }
  
  $scope.onClickStartHugeProcess = function () {
    console.log('onClickStartHugeProcess');
    hugeProcess();
  };
  
  $scope.onClickStartHugeProcessWithPromise = function () {
    console.log('onClickStartHugeProcessWithPromise');
    $q.when()
    .then(function () {
      return hugeProcess();
    });
  };
});

Answer №1

The problem with the code provided is that the hugeProcess function does not yield, causing it to hog the main UI thread and prevent other actions from happening while it runs, even though it is called asynchronously. This issue can be resolved by breaking up the process and implementing a delay using setTimeout or similar methods within Angular.

As highlighted by Sara Fox, the code snippet below is essentially equivalent to setting a timeout for hugeProcess:

$q.when()
.then(function () {
  return hugeProcess();
});

This is like:

setTimeout(hugeProcess, 0);

Since calling $q.when() with no arguments results in a resolved promise, adding a then callback only triggers the callback once the current tasks are completed, but still asynchronously.

Answer №2

After some exploration, I came across Web Workers and decided to implement them in my code for the first time.

app.controller('MainCtrl', function($scope, $q) {

  function hugeProcess () {
    var i = 0;
    var start = new Date().getTime();
    while (i++ < 100000) {
      console.log(i);
    }
    var end = new Date().getTime();
    var time = end - start;
    postMessage(time);
  }

  var blob = new Blob(["onmessage = " + hugeProcess.toString()]);

  // Get a reference to the blob URL of our worker 'file'.
  var blobURL = window.URL.createObjectURL(blob);
  var worker = new Worker(blobURL);

  worker.onmessage = function (message) {
    $scope.processTime = 'Done in ' + message.data  + 'ms';
    $scope.$apply()
  };

  $scope.onClickStartHugeProcessWithPromise = function () {
    console.debug('onClickStartHugeProcessWithPromise');
    $q(function () {
      worker.postMessage(''); // Start the worker.
    });
  };
});

I may not be using it correctly, but it accomplishes what I intended. Additionally, I came across the package ng-webworker for Angular, which seems to integrate promises with web workers, meeting my needs perfectly.

Many thanks to everyone who provided assistance.

Answer №3

If you're looking for a solution, Web Worker might be the right choice. I faced a similar issue and created an Angular plugin called ng-vkThread to simplify tasks like this.

Here's how you can use it:

/* Function to execute in a thread */
function bar(x, y){ 
    return x * y;
}

/* Create an object to pass to vkThread as an argument */
var parameter = {
   fn: bar      // <-- Function to execute
   args: [5, 10] // <-- Arguments for the function
};

/* Run the thread */
vkThread.exec(parameter).then(
   function (result) {
       console.log(result);  // <-- The thread returns 50 
    },
    function(error) {
        alert(error);  // <-- An error message is returned by the thread
    }

);

Check out the Live demo here!

--Vadim

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

WebClient executes JavaScript code

On my aspx page, there are JavaScript functions that handle paging. I am currently using the WebBrowser control to run these JavaScript functions by calling WebBrowser1_DocumentCompleted. WebBrowser1.Document.Window.DomWindow.execscript ("somefunction(); ...

Activate the action using the onclick interaction

window.addEventListener(mousewheelEvent, _.throttle(parallaxScroll, 60), false); My current setup involves an event listener that responds to a mousewheelEvent by executing a function. However, when attempting to directly trigger this function on a separa ...

"The orderBy function in AngularJS seems to be overlooked or not functioning properly within the

It seems like the orderBy function is being ignored in my code. Despite adding a console.log for testing purposes, the function doesn't appear to be called at all. As a result, the data is still displayed but remains unordered. Snippet of HTML Code ...

What is the most effective way to loop through HTML elements using wildcards in Puppeteer to extract innerText?

Seeking insights for educational purposes, I am in search of the reviews on this specific page . Each page contains 10 reviews, and I have a set of HTML selectors (previously used code) to extract these comments: #review_593124597 > div:nth-child(1) &g ...

What steps can be taken to remove the search parameter responsible for the error?

Imagine having a webpage that displays search results based on the parameters in the URL, like this: https://www.someurl.com/categories/somecategory?brands=brand1,brand2,brand3 This URL will show listings for only brand1, brand2, and brand3. Additionally ...

When using Next JS with StoryBook, an error may occur if styles are written in a module.scss file

Every time I try to add some styles to my ButtonWidget.scss file, I encounter an error in the console when running the command yarn storybook Error Code: ERROR in ./src/components/ButtonWidget/ButtonWidget.module.scss 1:0 Module parse failed: Unexpected ...

Generating new objects from API request in React and aggregating them into a single, comprehensive object

I have developed a program that utilizes Axios to fetch data through API calls. I aim to save the fetched result as an object within my this.state.matrixDictionary variable. However, each time I make another API call, the previous object gets replaced. My ...

Convert the JSON data received from a jQuery AJAX call into a visually appealing HTML table

Utilizing AJAX as the action, I have created a search form. In the success of the AJAX request, I am seeking a way to update a specific div without refreshing the entire page. Below is my form: <?php $properties = array('id' => &ap ...

Please rewrite the following sentence: "I am going to the store to buy some groceries."

As I navigate through my styled HTML page, an interesting sequence of events unfolds. When the Create New List button is clicked, a pink div emerges, contrasting with the orange hue of the All Lists div. At this moment, a new user has joined but hasn' ...

Unable to retrieve input value from dynamically-generated field with JQuery

There seems to be an issue with receiving a value from a static field when using the keyup method based on the input field class (.inputclass). Once a field is added dynamically, it does not get the value. Below is a sample code. Any help would be appreci ...

Display a button in a single row table

Here is my table markup: <table class="table table-condensed"> <thead> <tr> <th>id</th> <th>task</th> <th>date</th> </tr> </thead> ...

The directive's template is unable to access the scope due to isolating it

I am currently working on a directive with the goal of retrieving an attribute and displaying it from within the directive. Below is the code for the directive: angular.module('JJJ') .directive('jobCard', function () { return { ...

Sharing and displaying images on Sails JS platform

Using Sails JS, I am attempting to upload an image and display it in a view. Queries: The uploaded image is located in .tmp/uploads, how can I retrieve it from a view? Is there a method to access the uploaded image? The image's name is altered in ...

Remove the "href" from Zend2 navigation functionality

When using Zend2 navigation from an array passed in Zend\Navigation\Navigation, everything works smoothly if child items are opened on parent item mouse hover. However, undesirable actions occur when they are opened on mouse click, as the user is ...

Contrasting gatsby-theme-material-ui and gatsby-plugin-material-ui

I'm in the process of creating a website using Gatsby, and I'd like to incorporate Material UI, but I'm unsure about which plugin I should use. Here are my questions: What is the difference between these two options, and how can I integra ...

Oops! Make sure to explicitly allow the dependency @types/html2canvas by adding it to the "allowedNonPeerDependencies" option

After installing the html2canvas package in my Angular library project, I encountered an error when compiling in production mode using the command ng build --prod. The specific error message is as follows: ERROR: Dependency @types/html2canvas must be exp ...

What is the method for establishing bidirectional communication between separate directives without relying on $watch or $rootScope?

I am currently working on a directive with isolated scope that manages all recording activities such as starting and stopping recordings. Additionally, I need it to call specific callbacks in both directiveA and directiveB when recording starts or finishes ...

Adding a class to an element in AngularJS

I have a question about entering empty values in an input field and highlighting its boundary. I added a new class 'warning' for this purpose and created the following code. HTML: `<body ng-app="TestPage"> <form ng-controller="TestFor ...

Display a loading screen with a progress bar using React Native Expo

Currently, I am diving into the world of React Native and honing my skills using Expo. One of the tasks I've tackled is creating a loading screen for my app using npm react-native-progress. However, I'm curious if there is a way to replace the de ...

The Guide to Utilizing Autonomous Models in Directive

Hey there! I have a question regarding a radio button directive. In this directive, I pass a model for the collection that will be set to the selected radio button. var app = ChartsModules.getInstance().getModule("amkaiCharts.directives"); ...