Last active
September 24, 2021 21:23
-
-
Save webbower/57f4d0ac7e19010a0ecc235fdc4dd940 to your computer and use it in GitHub Desktop.
Complex Promise handling examples
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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('/'); | |
} | |
); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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