Ways to ascertain if all functions in the chain have been executed by Javascript's Q deferred()

Can we determine with the Javascript Q promise library when all the functions in the chain have been executed?

Below is a code snippet I found on this page (my question follows on from this):

testJSCallbacks();

function testJSCallbacks(){
    var i = 0,
        promise;

    for (i = 0; i < 5; i++) {
        //Make initial promise if one doesn't exist
        if (!promise) {
            promise = Q.fcall(getStep(i));
        }
        //Append to existing promise chain
        else {
            promise = promise.then(getStep(i));
        }
        //then function returns another promise that can be used for chaining.
        //We are essentially chaining each function together here in the loop.
        promise = promise.then(function (key) {
            //Log the output of step here
            console.log("Step 1 " + key);
            return key;
        })
        //then function takes a callback function with one parammeter (the data).
        //foo signature meets this criteria and will use the resolution of the last promise (key).
        .then(foo)
        //myCB will execute after foo resolves its promise, which it does in the onsuccess callback
        .then(myCB);
    }
}

function getStep(step) {
    return function () {
        return step;
    }
}

function foo(key) {
    //retrieve png image blob from indexedDB for the key 'key'. Assume that the database is
    //created and started properly
    var getRequest = transaction.objectStore("store").get(key),
        //Need to return a promise
        deferred = Q.defer();
    getRequest.onsuccess = function (event) {
        var result = event.target.result;
        if(result){
            console.log("Step 2 " + key + " Found");
        }else{
            console.log("Step 2 " + key + " not Found");  
        }
        deferred.resolve(result);
    }

    return deferred.promise;
}

function myCB (result){
    console.log("Step 3: " + result);
}

=============

In the provided code, both foo() and myCB() are executed 5 times.

I am wondering if there is a way to receive some sort of notification from the Q library indicating the final execution of myCB(), signaling that the queue is now 'empty' and all registered/deferred functions have been executed?

Thank you in advance.

Answer №1

Ah yes, indeed! I would go as far as saying that promises revolve around this very concept.

The magical solution to this is none other than drumroll .then!

Utilizing this method also entails the use of Q.all to handle a series of promises. Especially applicable when there's a loop involved. Without it, all we need is .then.

function testJSCallbacks(){
       var promises = [];
       for(var i = 0; i < 5; i++){
       ...
       promise = promise.then(function (key) {
            //Display the outcome of each step here
            console.log("Step 1 " + key);
            return key;
        })
        .then(foo)
        .then(myCB);
        promises[i] = promise;
    }
    return Q.all(promises); 
}

Afterwards, you can attach onto its completion:

testJSCallbacks().then(function(results){
        // All tasks have concluded without any rejections
 });

If there's one takeaway from this discussion - make sure to always return promises from methods :). Also, instead of executing myCB directly, just return the value and trigger myCB externally - much more dynamic :)

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

Button switch in Bootstrap 4

Currently in the process of designing a basic vehicle inspection form, I have an idea to utilize checkboxes as buttons for capturing true/false values. I've discovered that this task can be easily accomplished using Bootstrap 4 as indicated by their ...

Encountering a syntax error with the spread operator while attempting to deploy on Heroku

I'm encountering an error when attempting to deploy my app on Heroku: remote: SyntaxError: src/resolvers/Mutation.js: Unexpected token (21:16) remote: 19 | const user = await prisma.mutation.createUser({ remote: 20 | data: { r ...

Tips for creating a fixed AppBar and table headers that are stacked underneath each other on a single page while scrolling, using Material UI

Check out these screenshots of the AppBar and Table: View screenshot at the top of the page. Screenshot when scrolling down Take a look at the code for the AppBar and Table: <AppBar position="static" style = {{background : "#00009A"}}> ...

Unable to retrieve uploaded files within the controller

Update with the latest code that helps solve my problem $scope.uploadedFiles = []; $scope.upload = function(files) { $scope.uploadedFiles = files; angular.forEach(files, function(file) { if (file && !file.$error) { ...

Using jQuery to access the data attribute values

Within my HTML code, there is a span element: <span class="field" data-fullText="This is a span element">This is a</span> I am trying to access the data-fullText attribute. I attempted two different methods, but unfortunately, they both retur ...

Tips for determining which site was accessed

My store is linked to a grid and when it loads, it has multiple pages. Now, I need to display the page that contains a specific value. To achieve this, I make use of store.load({params: {'file': 'file33939'}});. Despite not knowing the ...

Tips for changing the <title> in an AngularJS one-page application

I am working on a single-page AngularJS application. The index.html file is structured as follows: <html ng-app="myApp" ng-controller="MyCtrl as myctrl"> <head> <link rel="stylesheet" href="my-style-sheet.css"> <title>{{ ...

Refreshing a webpage with JavaScript directly from the server (2021)

Utilizing Javascript, I have successfully implemented a cookie setting feature that allows users to switch between normal and classic theme versions on my website by clicking a checkbox. The backend of my application is powered by PHP. My goal is to access ...

Learn the process of downloading a pdf file with vuejs and bootstrap-vue

Having trouble uploading a PDF file to my browser and then downloading it afterwards. The upload is fine, but the download isn't working. This is how I am uploading: <b-form-file v-model="form.file" :state="Boolean(form.file)" placeholder="Choose ...

What is the process for exporting an NPM module for use without specifying the package name?

I am looking for a way to export an NPM module so that it can be used without specifying the package name. Traditionally, modules are exported like this: function hello(){ console.log("hello"); } module.exports.hello = hello; And then imported and ...

Is there a way to attach event listeners to raw HTML that has been imported using code?

I'm facing a challenge with importing SVG code embedded in an HTML file and using the v-html directive to render it. The issue is that I need to attach click events to the anchor tags within that imported file, which are not part of my main template. ...

Stop background scrolling with CSS overlay menu

Is there a way to create a CSS overlay menu that prevents the main content it covers from scrolling when the menu is active? In other words, I want users to be able to scroll through the menu without affecting the background content. I've managed to ...

Can you show me a way to display a dynamically created array component on an Angular2 template html?

One way I've been able to generate dynamic component instances is by choosing from pre-existing components. For instance, @Component({ selector: 'dynamic-component', template: `<div #container><ng-content></ng-conten ...

Activate a function upon the clicking of a button by utilizing a directive in Angular.js

In my directive, there is a function called "myFunction()", and in the template, I have a button. When the button is clicked, I want to execute the function without using ng-click for specific reasons. Instead, I am looking to assign a class to the button ...

Is there a way for me to choose a single file while executing the migrate-mongo up command?

Hey there! I'm looking to execute the command migrate-mongo up in just one specific file. Currently, when I run the command migrate-mongo up, it processes all pending migration files. Is there a way to target only one file for execution? For example: ...

What is the best way to add a `<div>` before or after a specific `<p>` element based on the client's height?

I am facing an issue with inserting a div before a paragraph element based on the given clientHeight. Specifically, I need to locate the closest paragraph element from the specified clientHeight and then add a div before or after that particular element. ...

Why isn't the DIV I created in JavaScript appearing when the page loads?

I've been struggling to get the DIV generated by the Javascript code, particularly in the function parameter id within creatediv('xdiv', html, 100, 100, 10, 10) where id = 'xdiv'. <!DOCTYPE html> <html> <head> &l ...

Using the SmartSheets API to Iterate Over a List to Determine the Variable of a Function

I have a group of numerical values listed below that are stored in a variable. [700000000084, 100000000051652, 8800000000000072, 280000000000004, 680000000000008, 880000000000006] My goal is to iterate through this list using the SmartSheets API to gathe ...

Utilize toggle functionality for page rotation with rxjs in Angular framework

Managing a project that involves a container holding multiple cards across different pages can be overwhelming. To address this, the screen automatically rotates to the next page after a set time interval or when the user presses the space bar. To enhance ...

Importing the class results in an undefined outcome

In the process of developing my Vue app, I'm focusing on creating some helper classes: File a.js: export default class Base {//...} File b.js: import Base from "./a" export default class Middle extends Base { // ... } File c.js: import Mi ...