簡體   English   中英

如何使用 JSObjectMakeDeferredPromise 從 Swift 調用返回承諾的 JavaScript 函數

[英]How to use JSObjectMakeDeferredPromise to call a function in JavaScript from Swift that returns a promise

我希望能夠從返回承諾的 JSContext 調用函數。 JSObjectMakeDeferredPromise 似乎是這樣做的機制,但文檔太少,我不確定如何去做。

任何人都可以提供一個在 JSContext 中調用一個返回承諾的函數的例子嗎?

WebKit 是一個開源項目。 我發現了一個與該功能相關的問題 這個函數更喜歡為未處理的承諾拒絕拋出異常。

所以你不能使用那個函數來返回一個承諾。 但是 JavaScriptCore 支持 Promise 關鍵字。 我使用 Xcode 11.4.1 在 macOS 上運行此腳本。 這很好用。

const promiseA = new Promise( (resolve, reject) => {
    emulator.downloadWithHandler( (response) => {
        var isFinish = response["isFinish"];
        var isCancelled = response["isCancelled"];
        var date = response["date"];

        console.log("isFinish: " + isFinish);
        console.log("isCancelled: " + isCancelled);
        console.log("date: " + date);

        if (isFinish || isCancelled) {
            resolve(date);
        }
    });
});

emulator.downloadWithHandler是一個本地回調,它會在某個時候在后台 DispatchQueue 上返回。 如果您想使用檢索該承諾並保留它。 調用context.objectForKeyedSubscript("promiseA")並使用JSManagedValue包裝它。


保留Promise的引用並沒有多大用處。 更重要的是如何訪問JSContext的變量和函數。

你可以調用 JSContext 的evaluateScript(_:) 如果您在腳本返回后保留上下文,則該上下文不會取消初始化並且可以使用。 從上下文中獲取對象,然后使用 JSValue 的invokeMethod(_:withArguments:)call(withArguments:)也可以工作。

NSHipster 有一篇關於該框架的精彩文章 你可以參考一下。


在我檢查文檔和 iOS 13+ 新 API 之后。 有什么可以確認的。 也就是說你可以使用JSObjectMakeDeferredPromise創建Promise ,這是 C 的方式。 為方便起見,我通過 Swift 方式創建了所需的函數並導出到 C。所以答案是:

let context = JSContext()
var ref = context.jsGlobalContextRef
context.evaluateScript("function resolve(value) { console.log(value); };")
var resolve = context.objectForKeyedSubscript("resolve")?.jsValueRef
context.evaluateScript("function reject(reason) { console.log(reason); };")
var reject = context.objectForKeyedSubscript("reject")?.jsValueRef

var exception: JSValueRef?
var promise = JSObjectMakeDeferredPromise(ref, &resolve, &reject, &exception)

(lldb) po promise
▿ Optional<OpaquePointer>
  ▿ some : 0x000000010c74ae78
    - _rawValue : (Opaque Value)

(lldb) p promise
(JSObjectRef?) $R4 = 0x000000010c74ae78

我不想再深入。 那只是意味着您可以將 JavaScriptCore 與 C 接口一起使用。 並且JSValue有 iOS 13+ 新的 C 風格的 init 方法, .init(newPromiseIn:fromExecutor:) 看起來一樣,但我不太確定。

如果你堅持使用C API。 這篇文章可能會有所幫助。

PS console.log方法是手工原生的導出日志方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM