从JSContext

时间:2017-09-12 16:53:35

标签: javascript ios swift promise

我正在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调用中将值传递给它,我将原始值设置为它(正如预期但值得一试):< / p>

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 个答案:

答案 0 :(得分:2)

在JSContext中模拟Promise工作流时会出现问题。 comTimout,setInterval等函数在JSContext中不可用。

但是,您可以通过将块传递给JSContext来从Javascript调用Swift代码。这是一段代码片段,展示了如何在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