Home > Software design >  How to properly resolve in a chained promise inside a catch block
How to properly resolve in a chained promise inside a catch block

Time:01-21

I am using an API which creates some assets on a server. After the creation which is a Promise I have to call process() on the asset which is another Promise API call.

I want to write a method which wraps everything together and returns the id of that asset even if the process part fails which should only log the error.

I don't know how to do that with promise changing since the catch block only contains the error and I can not resolve this.

Here is the code which I have so far;

const apicalls = async ():Promise<string> =>{

    return new Promise((resolve)=>{
        client.getEnviornment().then(environment=>{
            environment.createAsset({/* some data */}).then((asset)=>{
                resolve(asset.id); // this id I need
                return asset; // but I need also try to call process
            }).then(asset=>{
                asset.process(); // another api call which could fail
            }).catch(error=>{
                // if the error is only from process() I just want to log it.
                console.log(error);
            })
        })
    })
}

CodePudding user response:

You can refactor your existing function using async/await and try...catch...finally.

Note that unless you want the function to throw in the case that there's a problem before getting the asset ID (and if that's the behavior you desire, see the second example), you must use the return type of string | undefined because it's not guaranteed to get that far.

TS Playground

async function processAssetAndGetId (): Promise<string | undefined> {
  // because any of the steps leading up to getting the asset might fail,
  // this must be the type: string | undefined
  let id: string | undefined;
  try {
    // this could fail
    const environment = await client.getEnvironment();
    // this could fail, too
    const asset = await environment.createAsset({/* some data */});
    // set id to id of asset if we get this far
    ({id} = asset);
    // process the asset
    await asset.process();
  }
  catch (exception) {
    // if an exception is thrown at any point in the above block, log it to the console
    console.error(exception);
  }
  finally {
    return id;
  }
}

const id = await processAssetAndGetId(); // string | undefined

Or, don't handle potential exceptions before getting to the asset:

TS Playground

async function processAssetAndGetId (): Promise<string> {
  // this could fail
  const environment = await client.getEnvironment();
  // this could fail, too
  const asset = await environment.createAsset({/* some data */});
  try {
    // process the asset
    await asset.process();
  }
  catch (exception) {
    // if an exception is thrown at any point in the above block, log it to the console
    console.error(exception);
  }
  return asset.id;
}

const id = await processAssetAndGetId(); // string
  •  Tags:  
  • Related