Error: Promises must be managed correctly

I've been working on a timer-based function that is supposed to run once a week and create almost identical copies of existing documents. However, every time I try to execute it, I encounter the error message "Promises must be handled appropriately." I'm puzzled as to where I might have missed satisfying promises in my code structure. I have incorporated a return statement at each possible stage, so it's unclear to me what could be causing this issue.

Having launched approximately 40 cloud functions in the past, I thought I had a good grasp of how promises operate. Despite this experience, I seem to be overlooking something crucial in this scenario, and I can't pinpoint what exactly it is.

Below is the function in question:

exports.createRecurringDeals = functions.pubsub.schedule('0 0 * * 7').timeZone('Asia/Jerusalem').onRun((context) => {
    db.collection('recurring_deals').get().then(querySnapshot => {

        querySnapshot.forEach(bus => {
            const businessListDoc = bus.data();

            if (businessListDoc !== undefined) {
                const dealsList = businessListDoc.list as Array<String>

                return db.doc('businesses/' + bus.id).get().then(busDoc => {

                    const business = busDoc.data();

                    if (business !== undefined) {

                        dealsList.forEach(deal => {
                            return db.doc('deals/' + deal).get().then(snapshot => {
                                const oldDeal = snapshot.data();
                                if (oldDeal !== undefined) {

                                    const promises: any = [];

                                    const startTime = oldDeal.startTime + oldDeal.interval;
                                    const endTime = oldDeal.endTime + oldDeal.interval;

                                    const newDealDoc = db.collection('deals').doc();

                                    const newDeal = {
                                        id: newDealDoc.id,
                                        business_ID: business.id,
                                        business_name: business.name,
                                        business_address_text: business.address_text,
                                        business_address_lat: business.address_lat,
                                        business_address_long: business.address_long,
                                        business_phone_number: business.phone_number,
                                        business_image: business.restaurant_photos[0],
                                        business_categories: business.categories,
                                        business_sub_categories: business.sub_categories,
                                        discount: oldDeal.discount,
                                        timestamp_start: startTime,
                                        timestamp_end: endTime,
                                        gmt: oldDeal.gmt,
                                        amount: oldDeal.amount,
                                        claimers: [],
                                        active: true
                                    };

                                    promises.push(newDealDoc.set(newDeal));

                                    promises.push(db.doc('recurring_deals/' + business.id).update({ list: FieldValue.arrayRemove(oldDeal.id) }));

                                    promises.push(db.doc('recurring_deals/' + business.id).update({ list: FieldValue.arrayUnion(newDeal.id) }));

                                    return Promise.all(promises);

                                } else {
                                    return null;
                                };
                            });
                        });
                        return null;
                    } else {
                        return null;
                    };
                });
            } else {
                return null;
            };
        });
        return null;
    });
});

Answer №1

It seems like the suggestion is to add a .catch() block following the .then in case there is a failure with the Promise. As an example, you could modify your code from:

return db.doc('deals/' + deal).get().then(snapshot => {
    ...
});

to include a .catch() block like this:

return db.doc('deals/' + deal).get().then(snapshot => {
    ...
}).catch(err => console.log(err));

Answer №2

Let's begin by acknowledging that every promise must be managed - either through .catch or .then. One thing that you're overlooking is a handler for the Promise.all() function towards the end.

In addition, in the most recent versions of JavaScript, it is mandatory to include a catch block after a promise to handle any rejections, even if it has no specific action and even if there is a .then. You are missing a .catch for both the initial promise at the top (

db.collection('recurring_deals').get()
) and for the promise.all() call.

Include those, and the error will likely be resolved.

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

Retrieve all services within a Fargate Cluster using AWS CDK

Is there a way to retrieve all Services using the Cluster construct in AWS CDK (example in TypeScript but any language)? Here is an example: import { Cluster, FargateService } from '@aws-cdk/aws-ecs'; private updateClusterServices(cluster: Clus ...

Unable to make changes to the document

Having trouble updating a document by ID using mongoose and typescript. I'm testing the api and passing the id as a parameter. I've experimented with different methods of updating by ID, but for some reason, it's not working. Can update by ...

Transferring and displaying messages between PHP scripts

On my page (index.php), I have a simple layout consisting of two DIVs. The left side (#leftDIV) contains a form and another DIV (#messages) for displaying error messages. On the right side, there is another DIV (#mapAJAX) which houses a PHP script responsi ...

How can the executable path for Firefox be specified in Nightwatch?

I've been using nightwatch to run tests on both Chrome and Firefox with great success. While everything runs smoothly on Chrome, I'm facing an issue when trying to run tests on Firefox on my personal machine. Currently, due to Marionette's ...

The clearing of sessions is not supported by Node.js / Express.js

At the start, the application loads some users using Angularjs / $http.get(). As you scroll down, more users are loaded dynamically (infinite scroll). In addition to this, there are location filters on the page. Users can select a different Country and Ci ...

Refresh the webpage content by making multiple Ajax requests that rely on the responses from the previous requests

I am facing a challenge where I need to dynamically update the content of a webpage with data fetched from external PHP scripts in a specific sequence. The webpage contains multiple divs where I intend to display data retrieved through a PHP script called ...

The specified 'IArguments' type does not qualify as an array type

Currently working on crafting a personalized logger. It's a fairly straightforward process, but I'm running into some errors that are muddying up my output. Here's what I have so far: @Injectable() export class Logger { log(...args: any ...

Dealing with side effects in react/redux: Best practices and tips

Trying to find the best way to integrate an async side-effects handler into my react/redux setup has been quite a challenge. In my react-router-driven application, all the main containers at root level are smoothly dispatching actions and receiving update ...

Creating an HTML string and then displaying its outer HTML in IE10 can be easily achieved. Just write the

My task is to write an HTML string to an element and then retrieve the resulting outer HTML from that element. This needs to be operational in IE10, latest versions of FF, Chrome, Safari, Android, iOS Safari but does not have to support any older browsers. ...

Broadcasting events across the entire system

I'm trying to accomplish something specific in Angular2 - emitting a custom event globally and having multiple components listen to it, not just following the parent-child pattern. Within my event source component, I have: export class EventSourceCo ...

Leveraging the Recyclability Aspect of a ReactJS Modal

Looking for a way to make a modal dynamic without duplicating too much code. Any suggestions on how to achieve this? I've managed to separate the state from the layout using render props. interface State { open: boolean; } interface InjectedMod ...

Using setTimeout() and clearTimeout() alongside Promises in TypeScript with strict mode and all annotations included

Many examples of timer implementations using Promises in JavaScript seem overly complex to me. I believe a simpler approach could be taken. However, I am looking for a solution specifically tailored for TypeScript with the "strict": true setting and all ne ...

Utilizing jQuery to select an attribute containing a special character

There is a special div with a unique data-id: <div data-id=""> </div> I tried to target this div using jQuery, but it didn't work as expected: jQuery("[data-id='']").text('hello'); Can anyone help me on how to ...

AngularJS - Always keep an eye on a group of items

Looking to create a custom watcher for a collection within my application, I initially believed that Angular would have all the necessary tools at my disposal. I had access to $watch, both shallow and deep, as well as $watchCollection. A $digest cycle was ...

Discover the XPath of a post on a Facebook page with the help of HtmlUnit

I am trying to fetch the xpath of a Facebook post using HtmlUnit. To better understand my goal, you can check out these two related questions: Supernatural behaviour with a Facebook page HtmlUnit commenting out lines of Facebook page To replicate my pro ...

Switch between various height and width options using JavaScript

Is there a way to create a toggle that changes both the height and width of an element when it is clicked? <div class="flexbox-container" id="main" onclick="staybig()">Create Account</div> .flexbox-container { ...

Is there a way to access comprehensive data pertaining to an ID through Ajax?

I need help with an Ajax call. Below is the code I currently have: $.ajax({ async: true, url: 'test/', type: 'POST', datatype: 'text json', data: { id: id, }, success: function(data) { // Retrieve the da ...

Creating intricate structures using TypeScript recursively

When working with Angular and TypeScript, we have the power of generics and Compile-goodness to ensure type-safety. However, when using services like HTTP-Service, we only receive parsed JSON instead of specific objects. Below are some generic methods that ...

Select dropdown options in Material UI are overlapping

Exploring React for the first time and utilizing material-ui's select button feature. It displays highlighted text based on user input, but ideally this highlight should disappear upon selection of an element. https://i.stack.imgur.com/2ccaS.png How ...

An error occurred due to a missing value within the forEach loop

In my JavaScript object, I am encountering an issue with a key. resolve: function () { var result = this.initialValue; console.log('initial value:',result); // 5 this.functions.forEach(function (element, index) { ...