basant307/AI_Governance_Project
045
1[](https://www.npmjs.com/package/@open-draft/until)2 3# `until`4 5Gracefully handle a Promise using `async`/`await`.6 7## Why?8 9With 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:10 11```js12function getUser(id) {13 const data = await fetchUser(id)14 // Work with "data"...15}16```17 18In 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:19 20```js21function getUser(id)22 let data = null23 24 try {25 data = await asyncAction()26 } catch (error) {27 console.error(error)28 }29 30 // Work with "data"...31}32```33 34While 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.35 36This 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.37 38## Getting started39 40### Install41 42```bash43npm install @open-draft/until44```45 46### Usage47 48```js49import { until } from '@open-draft/until'50 51async function(id) {52 const { error, data } = await until(() => fetchUser(id))53 54 if (error) {55 return handleError(error)56 }57 58 return data59}60```61 62### Usage with TypeScript63 64```ts65import { until } from '@open-draft/until'66 67interface User {68 firstName: string69 age: number70}71 72interface UserFetchError {73 type: 'FORBIDDEN' | 'NOT_FOUND'74 message?: string75}76 77async function(id: string) {78 const { error, data } = await until<UserFetchError, User>(() => fetchUser(id))79 80 if (error) {81 handleError(error.type, error.message)82 }83 84 return data.firstName85}86```87 88## Frequently asked questions89 90### Why does `until` accept a function and not a `Promise` directly?91 92This has been intentionally introduced to await a single logical unit as opposed to a single `Promise`.93 94```js95// Notice how a single "until" invocation can handle96// a rather complex piece of logic. This way any rejections97// or exceptions happening within the given function98// can be handled via the same "error".99const { error, data } = until(async () => {100 const user = await fetchUser()101 const nextUser = normalizeUser(user)102 const transaction = await saveModel('user', user)103 104 invariant(transaction.status === 'OK', 'Saving user failed')105 106 return transaction.result107})108 109if (error) {110 // Handle any exceptions happened within the function.111}112```113 114### Why does `until` return an object and not an array?115 116The `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.117 118Compare these two examples:119 120```ts121const [error, data] = await until(() => action())122 123if (error) {124 return null125}126 127// Data still has ambiguous "DataType | null" type here128// even after you've checked and handled the "error" above.129console.log(data)130```131 132```ts133const result = await until(() => action())134 135// At this point, "data" is ambiguous "DataType | null"136// which is correct, as you haven't checked nor handled the "error".137 138if (result.error) {139 return null140}141 142// Data is strict "DataType" since you've handled the "error" above.143console.log(result.data)144```145 146> 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 of `error` and `data` as it was upon destructuring, ignoring any type guards you may perform later on.147 148## Special thanks149 150- [giuseppegurgone](https://twitter.com/giuseppegurgone) for the discussion about the original `until` API.151 