从 JSContext 中获取 JS Promise/async 函数的值
Posted
技术标签:
【中文标题】从 JSContext 中获取 JS Promise/async 函数的值【英文标题】:Get value from JS Promise/async function from within a JSContext 【发布时间】:2017-09-12 16:53:35 【问题描述】:我正在从 JSContext
中执行 javascript SDK,但是我无法从任何 SDK 的异步函数中获取值。我可以从JSContext
中得到一个 JavaScript 承诺,但我不知道如何解决它。我尝试了很多从 Promise 中获取价值的方法,但都失败了。
如果我尝试以下操作,我会得到[object Promise]
回复:
return self.jsContext.evaluateScript("new Promise(resolve => setTimeout(300, () => resolve([1, 2, 3])) )")!
如果我将 then
直接链接到 JS 上,我仍然会得到 [object Promise]
:
return self.jsContext.evaluateScript("new Promise(resolve => setTimeout(300, () => resolve([1, 2, 3])) ).then(val => val.json())")
如果我尝试从 Swift 调用该方法,我仍然会得到 [object Promise]
:
let jsPromise = self.jsContext.evaluateScript("new Promise(resolve => setTimeout(300, () => resolve([1, 2, 3])) )")
let promiseResult = jsPromise?.invokeMethod("then", withArguments: ["val => return val.json() "])
return promiseResult!
如果我在 Promise 之外声明一个 JS 变量,然后从 Swift 调用的 then
调用中将值传递给它,我会得到设置为它的原始值(正如预期的那样,但值得一试):
self.jsContext.evaluateScript("let tempVar = 'Nothing has happened yet!'")
let jsPromise = self.jsContext.evaluateScript("new Promise(resolve => setTimeout(300, () => resolve([1, 2, 3])) )")
let promiseResult = jsPromise?.invokeMethod("then", withArguments: ["val => tempVar = val "])
let tempVar = self.jsContext.evaluateScript("tempVar")
return tempVar!
如果我尝试使用*** await
并将 Promise 解析为变量,然后将该变量从 JSContext
中拉出,IU 会收到 EXC_BAD_INSTRUCTION
错误:
let jsPromise = self.jsContext.evaluateScript("let someVar = await new Promise(resolve => setTimeout(300, () => resolve([1, 2, 3])) )")
return self.jsContext.evaluateScript("someVar")!
在此先感谢,如果我遗漏了一些东西,我很抱歉,这对 Swift 来说还是很新的。
【问题讨论】:
如果你用断点调试它,你会在对象中看到什么? 【参考方案1】:在 JSContext 中模拟 Promise 工作流时存在问题。 JSContext中没有setTimout、setInterval等函数。
但是,您可以通过将块传递给 JSContext 来从 Javascript 调用 Swift 代码。这是一个代码 sn-p,它显示了如何在 JSContext 中找出错误。
var logValue = ""
didSet
print(logValue)
//block we can pass to JSContext as JS function
let showLogScript: @convention(block) (String) -> Void = value in
logValue = value
let jsContext = JSContext()
//set exceptionHandler block
jsContext?.exceptionHandler =
(ctx: JSContext!, value: JSValue!) in
print(value)
//make showLog function available to JSContext
jsContext?.setObject(unsafeBitCast(showLogScript, to: AnyObject.self), forKeyedSubscript: "showLog" as (NSCopying & NSObjectProtocol))
jsContext!.evaluateScript("showLog('this is my first name')") //this works
jsContext!.evaluateScript("showLog(setTimeout.name)") //it has issue
【讨论】:
以上是关于从 JSContext 中获取 JS Promise/async 函数的值的主要内容,如果未能解决你的问题,请参考以下文章
无法在 JavaScriptCore JSContext 中运行 proj4.js
jsContext全局函数调用与对象函数调用evaluateScript
iOS JS 交互之利用系统JSContext实现 JS调用oc方法