Skip to content

Commit

Permalink
Added base snapshot function
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-van committed Dec 28, 2023
1 parent 08a94a5 commit 6f50f1c
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/modern-async.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,4 @@ export { default as timeout } from './timeout.mjs'
export { default as TimeoutError } from './TimeoutError.mjs'
export { default as timeoutPrecise } from './timeoutPrecise.mjs'
export { default as toArray } from './toArray.mjs'
export { default as snapshot } from './snapshot.mjs'
60 changes: 60 additions & 0 deletions src/snapshot.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@

/**
* Immediately calls an asynchronous function and wraps its result into a promise that
* can only be resolved, not rejected, regardless of the state of the promised returned
* by the function.
*
* The returned promise will contain an object with the following fields:
*
* * `status`: A string, either "fulfilled" or "rejected", indicating the state of the
* original promise.
* * `value`: Only present if status is "fulfilled". The value that the promise was
* fulfilled with.
* * `reason`: Only present if status is "rejected". The reason that the promise was
* rejected with.
*
* This object structure is similar to the one used by the [`Promise.allSettled()`
* function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled).
*
* This function can be useful to make use of other functions in a fault-tolerant way.
*
* @param {Function} fct An asynchronous function
* @returns {Promise<any>} A promise that will always be resolved with an object containing
* a snapshot of the original promise state.
* @example
* import { snapshot, map, sleep } from 'modern-async'
*
* const array = [1, 2, 3]
*
* const result = await map(array, (v) => snapshot(async () => {
* await sleep(10) // waits 10ms
* if (v % 2 === 0) { // throws error on some values
* throw Error("error")
* }
* return v
* }))
*
* console.log(result)
* // prints:
* // [
* // { status: 'fulfilled', value: 1 },
* // { status: 'rejected', reason: Error: error },
* // { status: 'fulfilled', value: 3 }
* // ]
*/
async function snapshot (fct) {
try {
const res = await fct()
return {
status: 'fulfilled',
value: res
}
} catch (e) {
return {
status: 'rejected',
reason: e
}
}
}

export default snapshot
29 changes: 29 additions & 0 deletions src/snapshot.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

import { expect, test } from '@jest/globals'
import snapshot from './snapshot.mjs'
import delay from './delay.mjs'

test('snapshot base test', async () => {
const res1 = await snapshot(async () => {
await delay()
return 3
})

expect(typeof (res1) === 'object').toBeTruthy()
expect(res1.status).toStrictEqual('fulfilled')
expect(res1.value).toStrictEqual(3)
expect(res1.reason).toBeUndefined()
})

test('snapshot falure', async () => {
const res1 = await snapshot(async () => {
await delay()
throw new Error('error')
})

expect(typeof (res1) === 'object').toBeTruthy()
expect(res1.status).toStrictEqual('rejected')
expect(res1.value).toBeUndefined()
expect(res1.reason).toBeInstanceOf(Error)
expect(res1.reason.message).toStrictEqual('error')
})

0 comments on commit 6f50f1c

Please sign in to comment.