Skip to content

Instantly share code, notes, and snippets.

@webbower
Last active September 24, 2021 21:23
Show Gist options
  • Save webbower/57f4d0ac7e19010a0ecc235fdc4dd940 to your computer and use it in GitHub Desktop.
Save webbower/57f4d0ac7e19010a0ecc235fdc4dd940 to your computer and use it in GitHub Desktop.
Complex Promise handling examples
zhuLiDoTheThing(args)
// Application status codes can come from HTTP 2xx, 4xx, and 5xx responses. This `.then()` will attempt to resolve
// to Promise<codeString> or reject with an error if the code is missing from the response body.
.then(
response => {
if (response.code) {
// Forward the code from the response
return response.code;
}
// Code is missing from the response so we reject.
return Promise.reject(new Error('HTTP successful but code is missing'));
},
error => {
if (error.response?.code) {
// Returning a value from a rejection handler will forward a resolved Promise
return error.response.code;
// equivalent to `return Promise.resolve(error.response.code);`
}
// Code is missing from the response so we stay rejected.
return Promise.reject(new Error(error.message));
}
)
// We can be sure that the status code will be here so this only needs to handle how to communicate the status
// code to the user. If the status code is unexpected or unsupported by the UI here, then it will reject and
// forward to the error handling .`catch()` block at the end.
.then(code => {
switch(code) {
case AppCode.CREATED:
case AppCode.EXISTS:
showSuccessMessage();
break;
case AppCode.BAD_DATA:
showErrorMessage(badDataMessage);
break;
case AppCode.TIMEOUT:
showErrorMessage(timeoutMessage);
break;
case AppCode.EXCEPTION:
showErrorMessage(exceptionMessage);
break;
default:
// The code we have is unrecognized by the handler so Reject to error handler
throw new Error(`Unsupported response code: ${code}`);
}
})
// Handle all rejected cases
.catch(error => {
logger.error(error.message);
showErrorMessage(generalErrorMessage);
})
const appConfig = { redirectUrl: 'https://www.example.com/' };
const defaultRedirectUrl = appConfig.redirectUrl;
const urlParams = new URLSearchParams(location.search);
// Perform pre-check
checkStatusOnServer({})
.then(response => {
if (response.code === AppCode.SUCCESS) {
const sessionToken = urlParams.get('sessionToken');
if (sessionToken) {
// First choice for redirect URL is based on the sessionToken if present in the URL.
// If this fetch is successful, will return a Promise<urlString>
return fetchRedirectUrlFromSession(sessionToken)
.catch(error => {
if (error) {
// log error, but not reject since we can still redirect
logger.error(error.message);
}
// If the fetch fails, we recover and return a Promise<urlString>
return Promise.resolve(defaultRedirectUrl);
});
}
// If there is no sessionToken, we return the fallback redirect URL as a Promise<urlString>
return Promise.resolve(defaultRedirectUrl);
}
// If `checkStatusOnServer` is HTTP success but we don't have a successful app code response, reject with an error
return Promise.reject(new Error('Status is not ok'));
})
.then(
// All paths that can return Promise<urlString> will execute this
url => {
location.assign(url);
},
// Centralized failure handler. Log error reason and redirect to static location.
error => {
logger.error(error.message);
location.assign('/');
}
);
new Promise((resolve, reject) => {
showInitiMessage();
// Initiate data fetch
fetchDataToValidate(args).then(resolve, reject);
})
// Handle network errors
.catch(error => {
throw new Error(`Unable to fetch data for some reason: ${error.message}`);
})
// We got a successful response
.then(response => {
return response.text().then(text => {
try {
// Get the response body and attempt to parse it as JSON
return JSON.parse(text);
} catch (error) {
// Bad JSON. Reject the rest of the chain.
throw new Error(`Contains invalid JSON: ${error.message}`);
}
});
})
// We should have the parsed data ready to validate here
.then(json => {
const failures = validate(json);
if (failures.length > 0) {
// There were failures so reject.
throw new ValidationError(failures);
}
// No news is good news: No failures means we resolve with Promise<void>. New
})
// At this point, we have done all our processing and can communicate the outcome to the user
.then(
// No validation failures were found
() => {
showValidMessage();
},
// Handle all errors and validation failure
error => {
if (error instanceof ValidationError) {
// Handle validation failures
showValidationFailuresFromValidationError(error)
} else {
// Handle other errors
showGeneralErrorMessage(error.message);
}
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment