From bcc34949abd71b83752853cd9d0bb9d14da028d6 Mon Sep 17 00:00:00 2001 From: EnixCoda Date: Sat, 2 Jul 2022 23:23:51 +0800 Subject: [PATCH] feat: atomic async function --- src/utils/general.test.ts | 36 +++++++++++++++++++++++++++++++++++- src/utils/general.ts | 8 ++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/utils/general.test.ts b/src/utils/general.test.ts index 205acc8..acb3949 100644 --- a/src/utils/general.test.ts +++ b/src/utils/general.test.ts @@ -1,4 +1,4 @@ -import { resolveDiffGraphMeta } from './general' +import { atomicAsyncFunction, resolveDiffGraphMeta } from './general' it(`should resolve diff stat graph meta properly`, () => { const example = ` @@ -27,3 +27,37 @@ it(`should resolve diff stat graph meta properly`, () => { expect([meta.g, meta.r]).toEqual([g, r]) }) }) + +it(`should schedule atomic promises properly`, async () => { + const sleep = (duration: number) => new Promise(resolve => setTimeout(resolve, duration)) + + const recorder: string[] = [] + const sleepWithNoise = async (duration: number, noise: string) => { + await sleep(duration) + recorder.push(noise) + return noise + } + + const atomicSleep = atomicAsyncFunction(sleepWithNoise) + + recorder.length = 0 + const atomicReturns = await Promise.all([atomicSleep(200, 'a'), atomicSleep(100, 'b')]) + // Expected time sheet + // 0 100 200 300 + // [a ] + // [b ] + // Recorder: [a, b] + // + expect(recorder).toEqual(['a', 'b']) + expect(atomicReturns).toEqual(['a', 'b']) + + recorder.length = 0 + const normalReturns = await Promise.all([sleepWithNoise(200, 'a'), sleepWithNoise(100, 'b')]) + // Time sheet if not atomic + // 0 100 200 + // [a ] + // [b ] + // Recorder: [b, a] + expect(recorder).toEqual(['b', 'a']) + expect(normalReturns).toEqual(['a', 'b']) +}) diff --git a/src/utils/general.ts b/src/utils/general.ts index 619b889..a71dcf3 100644 --- a/src/utils/general.ts +++ b/src/utils/general.ts @@ -219,3 +219,11 @@ export function resolveDiffGraphMeta(additions: number, deletions: number, chang w = 5 - g - r return { g, r, w } } + +export function atomicAsyncFunction(fn: (...args: Args) => Promise) { + let last: Promise | undefined + return async (...args: Args) => { + last = last ? last.then(() => fn(...args)) : fn(...args) + return last + } +}