Ways to pause for the completion of multiple HTTP promises and display a modal exclusively when all promises result in failure

There are two separate HTTP calls on a page that need to be handled independently.

vm.$onInit = function() {
    ....
    ....
    //Retrieve all items during initialization
    ds.getAllItems().then(function(result){
      vm.items = result;
     },function(error){
      vm.errorInApi = true;
    });
    .....
    .....
}
vm.getTimes = function(){
    .....
    .....
    HttpWrapper.send(url,{"operation":'GET'}).then(function(times){
                    .....
}

If both APIs fail, then I want to display a modal pop-up.

I can set a variable to true and if the API calls fail, I will change it to false before displaying the modal.

The question is how long to wait for both APIs to complete?

Answer №1

Wondering... why not just flip the promises' polarity and leverage Promise.all()?

Promise.all() typically resolves only when all promises are resolved, but by inverting the promises, it will now resolve once they are all rejected...

var invert = p => new Promise((v, x) => p.then(x, v));

Promise.all([Promise.reject("Error 404"), Promise.reject("Error WTF")].map(invert))
       .then(v => console.log(v));

Building upon @guest271314's input, here's a deeper dive into how flipping promises can be employed for this scenario.

var invert = p => new Promise((v, x) => p.then(x, v)),
    prps   = [Promise.reject("Error 404"), Promise.reject("Error WTF")]; // previously rejected promises

myButton.addEventListener('click', function(e){
                                     setTimeout(function(...p){
                                                  p.push(Promise.reject("Error in Click Event Listener"));
                                                  Promise.all(p.map(invert))
                                                         .then(r => results.textContent = r.reduce((r,nr) => r + " - " + nr));
                                                }, 200, ...prps);
                                   });
<button id="myButton">Check</button>
<p id="results"></p>

If any of the promises—be it the earlier ones or those in the event listener logic—manage to resolve, you won't see any output at all.

Answer №2

To find out how many Promises have been rejected, you can use both async/await and .catch(). If the number of rejected Promises is equal to a specified value N, then take action accordingly.

Before doing this, as advised by @trincot, make sure to return the Promise from the function, return a value from the function in the .then() method, and use throw with an Error() in the .catch() or function passed as the second parameter in .then(). For more details, refer to Why is value undefined at .then() chained to Promise?

const N = 2;

function onInit() {
  return Promise.resolve("resolved")
}

function getTimes() {
  return Promise.reject("rejected");
}

const first = onInit();

document.querySelector("button")
.onclick = async function() {
  let n = 0;
  const firstP = await first.catch(() => ++n);
  const secondP = await getTimes().catch(() => ++n);
  if (n === N) {
    // do stuff if `n` is equal to `N`
  } else {
    // do other stuff
    console.log(n, N)
  }
};
<button>click</button>

Answer №3

If you're looking to handle multiple promises simultaneously, consider using Promise.all.

Start by ensuring that your functions return promises:

vm.$onInit = function() {
    ....
    ....
    return ds.getAllItems().then(function(result){
      vm.items = result;
     },function(error){
      vm.errorInApi = true;
    });
}
vm.getTimes = function(){
    .....
    .....
    return HttpWrapper.send(url,{"operation":'GET'}).then(function(times){
                    .....
    });
}

Once you have the promises from each function, create an array with them:

var promiseArray = [];
promiseArray.push(vm.$onInit());
...
promiseArray.push(vm.getTimes());

In the click handler where getTimes is called, add another push for that function.

You can then flip the promise results to detect if both are rejected:

// Flip promises so that a rejected one is regarded as fulfilled and vice versa:
promiseArray = promiseArray.map(promise => promise.then(res => { throw res }).catch(err => err));
// Check if all original promises were rejected
Promise.all(promiseArray).then(function() {
    // Run code when both promises fail
}).catch(err => err); // Ignore any errors

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

Discover how to utilize images encoded in base64 format within webhook embeds on Discord

Can someone help me with inserting an image into a Discord embed using a webhook? I have the image saved as a base64 string obtained from a database. However, my attempts so far have only resulted in an empty embed. const data = b64image.split(',&ap ...

Troubleshooting issues with a Node.js application on Azure App Service

Seeking assistance with deploying my first Node.js app on Azure App Service. Despite following Microsoft's guides and tutorials, my app is not functioning as expected. Although I can see my project in the Azure portal, when I attempt to access it via ...

Exploring AngularJS: A closer look at ngOptions expressions

I have been struggling to populate a Select element with a list of objects for ngOptions. Despite confirming that the data structure is correct and accessible, I cannot get the Select to show the options. Even when rendering the options expression on the p ...

Trouble with displaying my three.js 3D model

I've tried multiple solutions I found, but none have fixed the issue of not being able to display 3D models. Many have suggested that it could be a problem with the camera, but so far I haven't been able to resolve it. Any assistance would be gre ...

Want to achieve success with your AJAX calls in JavaScript? Consider using $.get

As I clean up my JavaScript code, I am looking to switch from using $.ajax to $.get with a success function. function getresults(){ var reqid = getUrlVars()["id"]; console.log(reqid); $.ajax({ type: "POST", url: "/api/ser/id/", ...

Encountered an npm ERR while executing the React project

I'm encountering an issue with running my React project. When I use the command "npx start", I receive the following error message. Can someone please assist me with this? npm ERR! could not determine executable to run npm ERR! A detailed log of thi ...

Create a script that ensures my website can be set as the homepage on any internet browser

I am currently in search of a way to prompt users on my website to set it as their homepage. Upon clicking "Yes," I would like to execute a script that will automatically make my website the user's browser homepage. I have come across a Similar Thread ...

Error Loading JQuery: The function $() is not recognized in the Shopify platform

I seem to be overlooking something obvious. I am using Shopify and have included jQuery in the head section of the theme.liquid file: <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> This script is placed rig ...

The legends on the Google chart are having trouble being displayed accurately

Take a look at the screenshot below to pinpoint the sample issue. While loading the graph UI with Google Charts, the legends data is showing up but not appearing correctly. This problem seems to occur more frequently on desktops than on laptops. Any advi ...

Creating a default menu within a specific route in Ember.js is a crucial step in

I have created a JSBin code for my Ember.js application which can be found here: When I click on Item A, I want the ABCD menu on the left to remain visible and not disappear. Thank you. ...

Creating an Angular directive that handles asynchronous attribute interpolation

I am facing an issue with my custom directive. In the link function attributes, I am trying to access the value of attributes.user. Here is how the directive is used in my view page: <div my-directive user="{{user.name}}"></div> The user obje ...

The AJAX success callback function failed to execute in cases where the dataType was set to JSONP during Cross domain Access

type = 'math'; var ajurl = "sample.com&callback=myhandler"; var datas = "cateid=" + cateid + "&type=" + type + "&pno=" + pno + "&whos=" + whos; $.ajax({ type: "GET", url: ajurl, data: datas, contentType: "application/json; ...

What is the process behind Stackoverflow's "Congratulations, you've earned a new badge" popup window?

Possible Duplicates: Custom notify box similar to StackOverflow Creating popup message like StackOverflow How does StackOverflow implement the "You earned a new badge" window? (the orange one that pops up at the top of the screen, I believe it&ap ...

Rendering based on conditions with a pair of values

I am trying to render my component only if the id is equal to either 15 or 12. My current approach is not working as expected, it only renders the component when I check for one id at a time, but I need to check for both. {query_estate_id === 15 || q ...

What is preventing me from utilizing my JavaScript constructor function externally?

I have a question about how I create my object: var myViewModel = new MyViewModel("other"); Why am I unable to call myViewModel.setHasOne(value) from outside the viewmodel? Whenever I try, I encounter this error message: Uncaught TypeError: Cannot ca ...

Retrieve the original content of a file uploaded by a user in Node.js using Express

Can we extract the raw file contents from a user uploaded file using Node.js Express? app.post('/images', upload.single('image'), async (req, res) => { const file = req.file ... I have come to realize that the file variable in t ...

Is there a way for me to retrieve the element that is linked to the ng-disabled attribute?

Is there a way to access the element with the ng-disabled attribute inside the function without passing it as a parameter? Here is the HTML element: <input class="needsDisabling" ng-disabled="isFieldDisabled()" type="text"> The isFieldDisabled fu ...

Searching for an array of IDs in Mongoose

I have created an API using Express.js and mongoose to find users based on their ids in an array. // Here is the array of user ids const followedIds = follow.map((f) => f.followed); console.log(followedIds); // This will log [ '5ebaf673991fc60204 ...

Modify/Adjust/Move the image uploaded by the user in VueJS before transferring it to an aws s3 bucket

Can you resize images in vuejs using vanilla js? I've managed to upload an image and send it to my s3 bucket using vue, but I'm struggling to figure out how to transform an image within vuejs and display it. Document.querySelector doesn't se ...

Invoking a function passed via props that utilizes react-router's features

I'm really struggling to grasp this problem. Is there anyone here who could help me out? I have a component where I pass a method called this.fetchContent as props named Filter. This method triggers an action creator that uses axios with Redux to fetc ...