@/utils#isAsyncFunction TypeScript Examples
The following examples show how to use
@/utils#isAsyncFunction.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Flow.ts From sandstone with MIT License | 6 votes |
private _while = <R extends void | Promise<void>>(condition: ConditionClass | CombinedConditions, callback: () => R, type: 'while' | 'do_while'): R => {
if (!isAsyncFunction(callback)) {
this.flowStatement(callback, {
callbackName: type,
initialCondition: type === 'while',
loopCondition: true,
condition,
})
return undefined as any
}
const { currentFunction: parentFunction } = this.datapack
return {
then: async (onfulfilled: () => void) => {
// In theory, we are already in the parent function so we shouldn't need to go back in it.
// Run the previous code
await this.flowStatementAsync(callback, {
callbackName: type,
initialCondition: type === 'while',
loopCondition: true,
condition,
})
// Go back in the parent function, because we don't know where the last code ended up.
this.datapack.currentFunction = parentFunction
// Finally enter the callback function
this.datapack.createEnterChildFunction(ASYNC_CALLBACK_NAME)
return onfulfilled?.()
},
} as PromiseLike<void> as any
}
Example #2
Source File: Flow.ts From sandstone with MIT License | 6 votes |
forRange = <R extends void | Promise<void>>(from: Score | number, to: Score | number, callback: (score: Score) => R) => {
const scoreTracker = from instanceof Score ? from : this.datapack.Variable(from)
// Small optimization: if we know the loop will run at least once, use a do while
let loop = this.while
if (typeof from === 'number' && typeof to === 'number' && to > from) {
loop = this.doWhile
}
if (!isAsyncFunction(callback)) {
return loop(scoreTracker.lowerThan(to), () => {
callback(scoreTracker)
scoreTracker.add(1)
})
}
return loop(scoreTracker.lowerThan(to), async () => {
await callback(scoreTracker)
scoreTracker.add(1)
})
}
Example #3
Source File: Flow.ts From sandstone with MIT License | 6 votes |
forScore = <R extends void | Promise<void>>(
score: Score | number,
// eslint-disable-next-line no-shadow
condition: ((score: Score) => ConditionType) | ConditionType,
// eslint-disable-next-line no-shadow
modifier: (score: Score) => void,
// eslint-disable-next-line no-shadow
callback: (score: Score) => R,
): R => {
const realScore = score instanceof Score ? score : this.datapack.Variable(score)
const realCondition = typeof condition === 'function' ? condition(realScore) : condition
if (!isAsyncFunction(callback)) {
return this.while(realCondition, () => {
callback(realScore)
modifier(realScore)
}) as any
}
return this.while(realCondition, async () => {
await callback(realScore)
modifier(realScore)
}) as any
}
Example #4
Source File: Flow.ts From sandstone with MIT License | 5 votes |
if = <R extends void | Promise<void>>(condition: ConditionType, callback: () => R): (R extends void ? ElifElseFlow<R> : ElifElseFlow<R> & PromiseLike<void>) => {
const ifScore = getConditionScore(this.commandsRoot.Datapack)
if (!isAsyncFunction(callback)) {
// /!\ Complicated stuff happening here.
let callbackFunction: FunctionResource
const { elseIf: realElseIf, else: realElse } = this.if_(condition, () => { callbackFunction = this.datapack.currentFunction!; callback() }, 'if', ifScore, false)
const { currentFunction } = this.datapack
// for Typescript
if (!currentFunction?.isResource) { throw new Error('Impossible') }
const ifCommandIndex = currentFunction.commands.length - 1
const switchToComplicatedIf = () => {
const command = currentFunction.commands[ifCommandIndex]
try {
// If this doesn't raise an error, it means the function didn't get inlined
this.datapack.resources.getResource(callbackFunction.path, 'functions')
// The function wasn't inlined - add the '/scoreboard players set' at the end of the function
if (!callbackFunction?.isResource) { throw new Error('Impossible') }
callbackFunction.commands.push(['scoreboard', 'players', 'set', ifScore, 1])
} catch (e) {
// The function was inlined - add the 'store success' part to the execute
currentFunction.commands[ifCommandIndex] = ['execute', 'store', 'success', 'score', ifScore, ...command.slice(1)]
}
// Add the reset
currentFunction.commands = [
...currentFunction.commands.slice(0, ifCommandIndex),
['scoreboard', 'players', 'reset', ifScore],
...currentFunction.commands.slice(ifCommandIndex),
]
}
return {
elseIf: (...args: Parameters<typeof realElseIf>) => {
switchToComplicatedIf()
return realElseIf(...args)
},
else: (cb: Parameters<typeof realElse>['0']) => {
switchToComplicatedIf()
return realElse(cb)
},
} as ElifElseFlow<void> as any
}
// First, specify the `if` didn't pass yet (it's in order to chain elif/else)
ifScore.reset()
// Async function
return this.if_(condition, async () => {
const returnedPromise = callback()
ifScore.set(1)
await returnedPromise
}, 'if', ifScore) as any
}
Example #5
Source File: Flow.ts From sandstone with MIT License | 4 votes |
private if_ = <R extends void | Promise<void>>(
condition: ConditionType,
callback: () => R,
callbackName: string,
ifScore: Score,
forceInlineScore = false,
): (R extends void ? ElifElseFlow<R> : ElifElseFlow<R> & PromiseLike<void>) => {
function ensureConsistency(nextCallback: () => void) {
if (!isAsyncFunction(callback) && isAsyncFunction(nextCallback)) {
throw new Error('Passed an asynchronous callback in a synchronous if/else if/else. If/else if/else must be all synchronous, or all asynchronous.')
}
if (isAsyncFunction(callback) && !isAsyncFunction(nextCallback)) {
throw new Error('Passed a synchronous callback in an asynchronous if/else if/else. If/else if/else must be all synchronous, or all asynchronous.')
}
}
if (!isAsyncFunction(callback)) {
// Register the current if
this.flowStatement(callback, {
callbackName,
initialCondition: true,
loopCondition: false,
condition,
forceInlineScore: forceInlineScore ? ifScore : undefined,
})
// We know the callback is synchronous. We must prevent the user to pass an asynchronous callback in else/else if.
return {
elseIf: (nextCondition: ConditionType, nextCallback: () => void) => {
// Ensure the callback is synchronous.
ensureConsistency(nextCallback)
return this.if_(this.and(this.not(ifScore.matches([0, null])), nextCondition), () => {
nextCallback()
ifScore.set(1)
}, 'else_if', ifScore, true)
},
else: (nextCallback: () => void) => {
// Ensure the callback is synchronous.
ensureConsistency(nextCallback)
this.if_(this.not(ifScore.matches([0, null])), nextCallback, 'else', ifScore, false)
},
} as ElifElseFlow<void> as any
}
const getPreviousPromise = () => this.flowStatementAsync(callback, {
callbackName,
initialCondition: true,
loopCondition: false,
condition,
})
const { currentFunction: parentFunction } = this.datapack
return {
elseIf: (nextCondition: ConditionType, nextCallback: () => Promise<void>) => {
// Ensure the callback is asynchronous.
ensureConsistency(nextCallback)
return this.if_(this.and(nextCondition, this.not(ifScore.matches([0, null]))), async () => {
// We keep the function where the "else if" is running
const { currentFunction: newCallback } = this.datapack
// Go back in the parent function
this.datapack.currentFunction = parentFunction
// Run the previous "if/else if" code
await getPreviousPromise()
// Now, we're going back in the current "else if"
this.datapack.currentFunction = newCallback
// First, we run all synchronous code (that will end up in the .mcfunction instantly called by the "else if")
const returnedPromise = nextCallback()
// We notice Sandstone that the condition has successfully passed
ifScore.set(1)
// Then we run the asynchronous code, that will create other .mcfunction called with /schedule.
await returnedPromise
}, 'else_if', ifScore)
},
else: (nextCallback: () => Promise<void>) => {
// Ensure the callback is asynchronous.
ensureConsistency(nextCallback)
/*
* We return the "if" result, which theoritically could allow our users to
* write `.if().else().if()`, however this is forbidden thanks to our TypeScript types.
* We have to return the result for the `then` part.
*/
return this.if_(this.not(ifScore.matches([0, null])), async () => {
// We keep the function where the "else" is running
const { currentFunction: newCallback } = this.datapack
// Go back in the parent function
this.datapack.currentFunction = parentFunction
// Run the previous "if"/"else if" code
await getPreviousPromise()
// Now, we're going back in the current "else"
this.datapack.currentFunction = newCallback
// And we run the "else" code.
await nextCallback()
}, 'else', ifScore)
},
then: async (onfulfilled: () => void) => {
// In theory, we are already in the parent function so we shouldn't need to go back in it.
// Run the previous "if/else if/else" code
await getPreviousPromise()
// Go back in the parent function, because we don't know where the last "if/else if/else" code ended up.
this.datapack.currentFunction = parentFunction
// Finally enter the callback function
this.datapack.createEnterChildFunction(ASYNC_CALLBACK_NAME)
return onfulfilled?.()
},
} as any
}