clean up container code a bit

This commit is contained in:
MapleLeaf
2021-12-15 11:21:30 -06:00
parent 20dc55d557
commit b7a3be73ee
3 changed files with 31 additions and 35 deletions

View File

@@ -85,7 +85,7 @@ test("state", async (t) => {
await assertSomeMessageHasContent(t, initialMessage) await assertSomeMessageHasContent(t, initialMessage)
setMessage!(newMessage) setMessage!(newMessage)
await root.awaitActions() await root.completion()
await assertSomeMessageHasContent(t, newMessage) await assertSomeMessageHasContent(t, newMessage)

View File

@@ -5,45 +5,65 @@ type Action =
| { type: "deleteMessage" } | { type: "deleteMessage" }
export class ReacordContainer { export class ReacordContainer {
channel: TextBasedChannels private channel: TextBasedChannels
message?: Message private message?: Message
actions: Action[] = [] private actions: Action[] = []
runningPromise?: Promise<void> private runningPromise?: Promise<void>
constructor(channel: TextBasedChannels) { constructor(channel: TextBasedChannels) {
this.channel = channel this.channel = channel
} }
async render(instances: string[]) { render(instances: string[]) {
const messageOptions: MessageOptions = { const messageOptions: MessageOptions = {
content: instances.join("") || undefined, // empty strings are not allowed content: instances.join("") || undefined, // empty strings are not allowed
} }
const hasContent = messageOptions.content !== undefined const hasContent = messageOptions.content !== undefined
await this.addAction( this.addAction(
hasContent hasContent
? { type: "updateMessage", options: messageOptions } ? { type: "updateMessage", options: messageOptions }
: { type: "deleteMessage" }, : { type: "deleteMessage" },
) )
} }
private async addAction(action: Action) { completion() {
return this.runningPromise ?? Promise.resolve()
}
private addAction(action: Action) {
const lastAction = this.actions[this.actions.length - 1] const lastAction = this.actions[this.actions.length - 1]
if (lastAction?.type === action.type) { if (lastAction?.type === action.type) {
this.actions[this.actions.length - 1] = action this.actions[this.actions.length - 1] = action
} else { } else {
this.actions.push(action) this.actions.push(action)
} }
await this.runActions() this.runActions()
} }
private async runActions() { private runActions() {
if (this.runningPromise) { if (this.runningPromise) return
return this.runningPromise
this.runningPromise = new Promise((resolve) => {
// using a microtask to allow multiple actions to be added synchronously
queueMicrotask(async () => {
let action: Action | undefined
while ((action = this.actions.shift())) {
try {
await this.runAction(action)
} catch (error) {
console.error(`Failed to run action:`, action)
console.error(error)
}
}
resolve()
this.runningPromise = undefined
})
})
} }
const runAction = async (action: Action) => { private async runAction(action: Action) {
if (action.type === "updateMessage") { if (action.type === "updateMessage") {
this.message = await (this.message this.message = await (this.message
? this.message.edit(action.options) ? this.message.edit(action.options)
@@ -55,28 +75,4 @@ export class ReacordContainer {
this.message = undefined this.message = undefined
} }
} }
this.runningPromise = new Promise((resolve) => {
// using a microtask to allow multiple actions to be added synchronously
queueMicrotask(async () => {
let action: Action | undefined
while ((action = this.actions.shift())) {
try {
await runAction(action)
} catch (error) {
console.error(`Failed to run action:`, action)
console.error(error)
}
}
resolve()
})
})
await this.runningPromise
this.runningPromise = undefined
}
awaitActions() {
return this.runningPromise ?? Promise.resolve()
}
} }

View File

@@ -12,12 +12,12 @@ export function createRoot(target: ReacordRenderTarget) {
return { return {
render: (content: ReactNode) => { render: (content: ReactNode) => {
reconciler.updateContainer(content, containerId) reconciler.updateContainer(content, containerId)
return container.awaitActions() return container.completion()
}, },
destroy: () => { destroy: () => {
reconciler.updateContainer(null, containerId) reconciler.updateContainer(null, containerId)
return container.awaitActions() return container.completion()
}, },
awaitActions: () => container.awaitActions(), completion: () => container.completion(),
} }
} }