I want to use Vapor(a Web framework made with Swift) and JavaScriptCore(Apple's JS engine) to process some requests. Vapor supports async/await, which makes handling HTTP requests very easy, like this:
func routes(_ app: Application) throws {
app.get("myrequestpath") { req async throws -> String in
let result = await myAsyncFunction()
return result
}
}
myAsyncFunction() handles the processing to return the desired result and some of the processing I do is in JavaScript, executed in JavaScriptCore. I have no problem with interacting with JavaScriptCore, I can call the JS functions and JS can call the Swift functions I give access to.
I want to be able to initiate a JS function from Swift, wait for the async code in JS to finish its job and then pass the result to Swift async code for further processing.
The problem is, JavaScript itself has async/await that works slightly differently than the one in Swift.
In JavaScript, async functions return a Promise object that later resolves once the code block inside it calls the resolve or reject functions.
As a result, I can't simply await a JS function because it will return a Promise object right away and Swift will continue execution:
func myAsyncFunction() async -> Bool {
let jsContext = JSEngine().evaluateScript(myJSCode)
let result = await jsContext.objectForKeyedSubscript("myAsyncJSFunction").call(withArguments: [data])
return result
}
I would love to do that but I can't, the result will be a Promise object that doesn't mean anything in Swift(right).
As a result, what I need is, to write an async Swift function that pauses until the JS function calls back the resolve or reject function.
Something like this maybe?:
func myAsyncFunction() async -> Bool {
let jsContext = JSEngine().evaluateScript(myJSCode)
let result = await {
/*
A function that I can pass to JS and the JS can call it when it's ready, return the result to Swift and continue execution
*/
}
return result
}
Any ideas how to achieve that?