I am not really sure I understand your question. For the most part, when using async/await, you can think of...and therefor write...asynchronous code like you write synchronous code. You don't have to do anything different, and if you have good error handling skills with synchronous code, then the same skills should apply with async/await code.
Consider:
async doSomeAsyncWork() {
try {
const requiredResult1 = await someAsyncServiceCall(...);
let transform = someSyncUtilityCall(requiredResult1);
const optionalResult2 = await someOtherAsyncServiceCall(...);
transform = {
...transform,
...optionalResult2
};
return transform;
} catch (err) {
throw new Error(...);
}
}
The catch will handle errors from all three calls...synchronous or asynchronous. If you need to handle one particular call in a unique way:
async doSomeAsyncWork() {
try {
const requiredResult1 = await someAsyncServiceCall(...);
let transform = someSyncUtilityCall(requiredResult1);
try {
const optionalResult2 = await someOtherAsyncServiceCall(...);
transform = {
...transform,
...optionalResult2
};
} catch {
transform.noOptionalResult = true;
}
return transform;
} catch (err) {
throw new Error(...);
}
}
It is just "normal" try/catch error handling. Nothing particularly special here. You could, of course, refactor the second example above to be simpler and easier to read and maintain:
async doSomeAsyncWork() {
try {
const requiredResult1 = await someAsyncServiceCall(...);
let transform = someSyncUtilityCall(requiredResult1);
return doSomeMoreAsyncWork(transform);
} catch (err) {
throw new Error(...);
}
}
async doSomeMoreAsyncWork(transform) {
try {
const optionalResult2 = await someOtherAsyncServiceCall(...);
transform = {
...transform,
...optionalResult2
};
} catch {
transform.noOptionalResult = true;
}
return transform;
}