Gathering detailed insights and metrics for @open-draft/until
Gathering detailed insights and metrics for @open-draft/until
Gathering detailed insights and metrics for @open-draft/until
Gathering detailed insights and metrics for @open-draft/until
Gracefully handle Promises using async/await without try/catch.
npm install @open-draft/until
Module System
Min. Node Version
Typescript Support
Node Version
NPM Version
531 Stars
53 Commits
11 Forks
5 Watching
1 Branches
8 Contributors
Updated on 21 Nov 2024
TypeScript (94.43%)
JavaScript (5.57%)
Cumulative downloads
Total Downloads
Last day
-0.8%
773,988
Compared to previous day
Last week
4.7%
3,967,661
Compared to previous week
Last month
13.8%
16,374,814
Compared to previous month
Last year
42%
151,458,982
Compared to previous year
6
until
Gracefully handle a Promise using async
/await
.
With the addition of async
/await
keywords in ECMAScript 2017 the handling of Promises became much easier. However, one must keep in mind that the await
keyword provides no standard error handling API. Consider this usage:
1async function getUser(id) { 2 const data = await fetchUser(id) 3 // Work with "data"... 4}
In case fetchUser()
throws an error, the entire getUser()
function's scope will terminate. Because of this, it's recommended to implement error handling using try
/catch
block wrapping await
expressions:
1async function getUser(id){ 2 let data = null 3 4 try { 5 data = await asyncAction() 6 } catch (error) { 7 console.error(error) 8 } 9 10 // Work with "data"... 11}
While this is a semantically valid approach, constructing try
/catch
around each awaited operation may be tedious and get overlooked at times. Such error handling also introduces separate closures for execution and error scenarios of an asynchronous operation.
This library encapsulates the try
/catch
error handling in a utility function that does not create a separate closure and exposes a NodeJS-friendly API to work with errors and resolved data.
1npm install @open-draft/until
1import { until } from '@open-draft/until' 2 3async function getUserById(id) { 4 const { error, data } = await until(() => fetchUser(id)) 5 6 if (error) { 7 return handleError(error) 8 } 9 10 return data 11}
1import { until } from '@open-draft/until' 2 3interface User { 4 firstName: string 5 age: number 6} 7 8interface UserFetchError { 9 type: 'FORBIDDEN' | 'NOT_FOUND' 10 message?: string 11} 12 13async function getUserById(id: string) { 14 const { error, data } = await until<UserFetchError, User>(() => fetchUser(id)) 15 16 if (error) { 17 return handleError(error.type, error.message) 18 } 19 20 return data.firstName 21}
until
accept a function and not a Promise
directly?This has been intentionally introduced to await a single logical unit as opposed to a single Promise
.
1// Notice how a single "until" invocation can handle 2// a rather complex piece of logic. This way any rejections 3// or exceptions happening within the given function 4// can be handled via the same "error". 5const { error, data } = until(async () => { 6 const user = await fetchUser() 7 const nextUser = normalizeUser(user) 8 const transaction = await saveModel('user', user) 9 10 invariant(transaction.status === 'OK', 'Saving user failed') 11 12 return transaction.result 13}) 14 15if (error) { 16 // Handle any exceptions happened within the function. 17}
until
return an object and not an array?The until
function used to return an array of shape [error, data]
prior to 2.0.0
. That has been changed, however, to get proper type-safety using discriminated union type.
Compare these two examples:
1const [error, data] = await until(() => action()) 2 3if (error) { 4 return null 5} 6 7// Data still has ambiguous "DataType | null" type here 8// even after you've checked and handled the "error" above. 9console.log(data)
1const result = await until(() => action()) 2 3// At this point, "data" is ambiguous "DataType | null" 4// which is correct, as you haven't checked nor handled the "error". 5 6if (result.error) { 7 return null 8} 9 10// Data is strict "DataType" since you've handled the "error" above. 11console.log(result.data)
It's crucial to keep the entire result of the
Promise
in a single variable and not destructure it. TypeScript will always keep the type oferror
anddata
as it was upon destructuring, ignoring any type guards you may perform later on.
until
API.No vulnerabilities found.
Reason
no binaries found in the repo
Reason
no dangerous workflow patterns detected
Reason
license file detected
Details
Reason
Found 5/18 approved changesets -- score normalized to 2
Reason
9 existing vulnerabilities detected
Details
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Score
Last Scanned on 2024-11-18
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More