Skip to content

Commit

Permalink
fix actionAsync when using promises that resolve immediately (#225)
Browse files Browse the repository at this point in the history
* fix actionAsync when using promises that resolve immediately

* change test name
  • Loading branch information
xaviergonz committed Oct 29, 2019
1 parent 69e8382 commit 305a383
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
* Fix for `actionAsync` when awaiting promises that resolve immediately.

# 5.5.1

* Fix for `actionAsync` giving errors when it didn't await a task inside.
Expand Down
12 changes: 11 additions & 1 deletion src/action-async.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ interface IActionAsyncContext {
args: IArguments
}

let taskOrderPromise = Promise.resolve()
const emptyFunction = () => {}

const actionAsyncContextStack: IActionAsyncContext[] = []

export async function task<R>(value: R | PromiseLike<R>): Promise<R> {
Expand All @@ -34,7 +37,14 @@ export async function task<R>(value: R | PromiseLike<R>): Promise<R> {
currentlyActiveIds.delete(runId)

try {
return await value
const ret = await value

// we use this trick to force a proper order of execution
// even for immediately resolved promises
taskOrderPromise = taskOrderPromise.then(emptyFunction)
await taskOrderPromise

return ret
} finally {
// only restart if it not a dangling promise (the action is not yet finished)
if (unfinishedIds.has(runId)) {
Expand Down
23 changes: 23 additions & 0 deletions test/action-async.ts
Original file line number Diff line number Diff line change
Expand Up @@ -534,3 +534,26 @@ test("complex case", async () => {
expectNoActionsRunning()
expect(values).toEqual([1, 2, 3])
})

test("immediately resolved promises", async () => {
mobx.configure({ enforceActions: "observed" })
const values = []
const x = mobx.observable({ a: 1 })
mobx.reaction(() => x.a, v => values.push(v), { fireImmediately: true })

const f1 = actionAsync("f1", async () => {
await task(Promise.resolve(""))
x.a = await task(Promise.resolve(3))
})

const f2 = actionAsync("f2", async () => {
const f1Promise = f1()
x.a = 2
x.a = await task(Promise.resolve(3))
await task(f1Promise)
})

await f2()
expect(values).toEqual([1, 2, 3])
expectNoActionsRunning()
})

0 comments on commit 305a383

Please sign in to comment.