Maya
Maya

Reputation: 369

Firebase function: nested async requests

I am struggling with the following relatively simple piece of code:

return Promise.all(promises)
   .then(results => {
        results.forEach(element => {
            var mainKey = element.key;
            var mainValue = element.val();

            if(mainKey.toString().startsWith('us_', 0)) {
                text = text + '\n\nUser id : ' + mainKey + '\n';
                Object.keys(mainValue).forEach(function(key) {
                    text = text + mainValue[key];
                });
            }
            if(mainKey.toString().startsWith("cr_", 0)) {
                text = text + 'Creation id: ' + mainKey;
                Object.keys(mainValue).forEach(function(key) {
                    console.log(key, mainValue[key]);
                    text = text + mainValue[key];
                });
                const file = bucket.file(value["thumbnail"]); 
    //START of another level of async code 
                var url =  file.getSignedUrl({
                action: 'read',
                expires: '03-09-2491'
                }).then(signedUrls => {
                    text = text + 'URL: ' + signedUrls[0];
                    return text;
            });  
    //END of another level of async code  
            }
        });
        return sendMail(orderid, text);
    }).catch((error) => {
        console.log("sendMail failed : "+ error);
    });

There are a few async requests (batch A) being executed using Promises.all(). So far it works as expected: all promises executed successfully and return what they’re supposed to. Now I am required to add another layer of async requests (batch B), which use data from batch A as parameters. So to my understanding it should be another Promise.all() call inside “then” block of batch A.

Is my understanding correct or is there an easier way to implement this? Could you please provide code sample demonstrating solution described above?

Upvotes: 0

Views: 460

Answers (1)

Kraylog
Kraylog

Reputation: 7563

Yes, you are basically correct.

The then clause allows you to run code that uses the result of asynchronous calls. You can then run more asynchronous calls and return those promises.

The trick to make the code nice, is that when you return a promise in a then clause, the result of the next then will be the result of that promise. In other words, the promises get flattened - instead of Promise-of-Promise-of-Value, you get again Promise-of-Value.

Promise.all(promiseList)
  .then(results => Promise.all(createNewPromises(results)))
  .then(moreResults => doStuffWithMoreResults(moreResults))
  .catch(err => somethingBadHappened(err))

Upvotes: 1

Related Questions