Determining the specific condition that failed in a series of condition checks within a TypeScript script

I am currently trying to determine which specific condition has failed in a set of multiple conditions. If one does fail, I want to identify it. What would be the best solution for achieving this?

Here is the code snippet that I am using:

const multiCondition =
  (await firstCondition()) &&
  (await secondCondition()) &&
  (await thirdCondition());

if (multiCondition) {
...
} else {
  // Failed! Which condition caused the failure?
}

Edit:

Note: Each condition is dependent on the success of the previous one.

Answer №1

At this moment, your promises are executing serially. Is this by design? If you prefer them to run in parallel, you can easily check the status of each using Promise.allSettled.

If you want them to execute sequentially, you could loop through all the conditions and stop if any fails, returning a failure status for the remaining promises. If all conditions pass, it will return an empty object.

const conditions = [firstCondition, secondCondition, thirdCondition];

const result = await conditions.reduce(async (status, condition, index) => {
   // Skip running current condition if we've already failed
   // Return failure status instead
   if(status.failed) {
     return status;
   }

   // Run the condition
   const test = await condition();

   // Return accumulator if successful, set status as failed if not
   return test ? status : { failed: true, failedAt: index }
}, {});

if(result.failed) {
   console.log('Condition failed: ', conditions[result.failedAt]);
}

You can simplify the code above like this:

const conditions = [firstCondition, secondCondition, thirdCondition];

const result = await conditions.reduce(async (status, condition, index) =>
  status.failed ?
  status :
  await condition() ?
  status :
  { failed: index },
  {}
);

if('failed' in result) {
   console.log('Condition failed: ', conditions[result.failed]);
}

Next, organize it into a utility function:

const promiseAnd = async (...conditions) => await conditions.reduce(async (status, condition, index) =>
  status.failed ?
  status :
  await condition() ?
  status :
  { failed: index },
  {}
);

const { failed } = await promiseAnd(firstCondition, secondCondition, thirdCondition);
if(failed) {
  console.log(`Promise ${failed} failed`);
}

Answer №2

const check1 = await validateFirst();
const check2 = await validateSecond();
const check3 = await validateThird();

const allChecks =
  check1 &&
  check2 &&
  check3;

if (allChecks) {
...
} else {
  // Error on which condition?
  // - Check 1
  // - Check 2
  // - Check 3
}

Answer №3

An effective approach is to utilize separate 'if' statements for each condition.

Answer №4

Here is my approach to achieving the desired outcome:

const criteria = [await conditionOne(), await conditionTwo(), await conditionThree()];

// checking all conditions
const areAllMet = criteria.reduce((current, next) => current && next);

if (areAllMet) {
  // success
} else {
  if (!criteria[0]) {
    // condition one failed
  } else if (!criteria[1]) {
    // condition two failed
  } else if (!criteria[2]) {
    // condition three failed
  } else {
    throw new Error('Unexpected error occurred');
  }
}

Answer №5

To efficiently exit the surrounding function, I recommend using guard clauses. Since your async checks are already executed sequentially, you can simplify the code like this:

if (!await firstCondition()) {
  // first condition failed
  return; // or throw
}

if (!await secondCondition()) {
  // second condition failed
  return; // or throw
}

if (!await thirdCondition()) {
  // third condition failed
  return; // or throw
}

// all conditions passed successfully
// ...

If you prefer not to exit, you have the option of using else-if statements instead.

if (!await thirdCondition()) {
  // first condition failed
} else if (!await secondCondition()) {
  // second condition failed
} else if (!await thirdCondition()) {
  // third condition failed
} else {
  // all conditions passed successfully
  // ...
}

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

Incorporate JavaScript data into your Laravel project

I am having an issue with adding form data to a database using JavaScript. The postData is correctly being read as I can see in an alert message, but the URL is not executing. I have tried it with both 'donorlist' and '/donorlist'. $(d ...

Enhancing the efficiency of JavaScript code

Imagine you have a web application processing 1,000,000 user logins per hour. and the code below is executed during each user login: if (DevMode) { // make an Ajax call } else if (RealMode) { // make another Ajax call } else { // Do something ...

Angular 2 template can randomly display elements by shuffling the object of objects

I am working with a collection of objects that have the following structure: https://i.stack.imgur.com/ej63v.png To display all images in my template, I am using Object.keys Within the component: this.objectKeys = Object.keys; In the template: <ul ...

What is the best way to display the data model in Angular as HTML?

I am facing an issue with my data-model where it needs to be converted or displayed as HTML, but currently it is only appearing as plain text. Here is the HTML code snippet: <div ng-repeat="item in ornamentFigures" class="ornament-item"> <la ...

What could be causing the React state to not function properly when using data from an external class?

Recently diving into the world of Javascript and React, I decided to challenge myself by creating a basic calculator. My strategy was to separate the calculator logic into its own class. As I am currently testing it out, I encountered a peculiar issue. It ...

Encountering a typescript error: Attempting to access [key] in an unsafe manner on an object of

I have recently developed a thorough equality checking function. However, I am encountering an issue with the highlighted lines in my code. Does anyone have any suggestions on how to rectify this problem (or perhaps explain what the error signifies)? Her ...

Assistance needed with WebSocket and Node.js: Unable to connect to wss://domain:8080 - Issue is not specific to any browser

Greetings, this is my initial inquiry on stack overflow so I'll give it my best shot. Despite going through numerous related questions, I haven't found the solution to my issue. I recently delved into Node.js because I required websockets for ce ...

Providing properties to the main Vue.js components

An Issue I'm Facing I am currently attempting to pass a prop to my root constructor. To achieve this, I have been exploring the use of propsData, which I learned about from this resource: var appComponent = Vue.component('app', require(&ap ...

Enhancing the node module of a subpackage within Lerna: A step-by-step guide

I recently integrated lerna into my workflow to streamline the installation of all node modules for multiple sub packages with just one command. Currently, I'm only utilizing the lerna bootstrap feature. Here's a snippet from my lerna.json: { & ...

Encountering difficulties with displaying error messages on the Material UI datepicker

I am currently utilizing React Material UI There is a need to display an error based on certain conditions that will be calculated on the backend. Although I have implemented Material UI date picker, I am facing issues with displaying errors. import * as ...

The best practices for utilizing getStaticProps with Firebase

I am completely new to Next.js and am struggling to make the getStaticProps function work properly. import firebase from '../firebase' export default function Home({ posts }) { return ( <div> <h1>All Posts</h1> ...

Updating component (`App`) during the rendering of another component is not allowed

I have encountered an issue with a react component that I am struggling to resolve. It involves a radial knob control, similar to a slider, and I am trying to achieve two main objectives: Adjust the knob and pass its value up to the parent component for ...

The quickForm Meteor encountered an exception in the template helper: There was an error stating that Recipes is not within the window

I'm having trouble getting the app to work on Meteor. The quickform is not connecting to my Collection. "Error: Recipes is not in the window scope" Can anyone offer assistance with this issue? Below is my quickform code: <template name="NewRe ...

performing resolver when needed in angular version 5

I have been working on a project using Angular and recently updated it from version 4.2 to Angular 5. Although I haven't utilized any new features introduced in Angular 5 yet. My current task involves executing a resolver on a specific route when a c ...

Retrieve all data points if both latitude and longitude are present in the XML dataset

XML data to retrieve details <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <results> <result> <Country_Code>IN</Country_Code> <Country_Name>India</Country_Name> <Region_Nam ...

Loading remote content on a server for my Firefox OS application - On the Web and FxOS device

I haven't come across this issue in any forum, so I decided to reach out here. I'm encountering a problem with my FirefoxOS app on my FirefoxOS device (Geeksphone Developer Preview) when trying to retrieve remote content from the server. I am m ...

Using Gmail in conjunction with Heroku for email delivery

After completing an order in my web app, I want to automatically send a confirmation email. I decided to use Nodemailer as it is a popular npm package for this purpose. I successfully coded the functionality and tested it in my local environment. Howeve ...

How to fix the issue of the mobile Chrome bar occupying part of the screen height in CSS

I am encountering a well-known issue with my collapsible scrollable bar implemented in Bootstrap. The problem occurs when scrolling on mobile devices, as the search bar takes up space from the sidebar's 100% height, causing the scrollbar to not reach ...

Adjust Fabric js Canvas Size to Fill Entire Screen

Currently, I am working with version 4.3.1 of the Fabric js library and my goal is to adjust the canvas area to fit its parent div #contCanvasLogo. I have tried multiple approaches without success as the canvas continues to resize on its own. Below is the ...

Update the second dropdown menu depending on the selection made in the first dropdown menu

While I know this question has been posed previously, I'm struggling to apply it to my current situation. In my MySQL database, I have a table named "subject" that includes columns for subject name and subject level. Here's an example: Subject ...