[英]How do I wait for a callback to resolve a promise in JS? Sync iOS WKWebView and JS
[英]wait an async callback to sync
我想包裝一個SDK異步api進行同步,代碼如下所示:
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
__block BOOL _isLogined;
__block BOOL _isCallback = NO;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^ {
//Put your heavy code here it will not block the user interface
[[SDKPlatform defaultPlatform] SDKIsLogined:^(BOOL isLogined){
_isLogined = isLogined;
_isCallback = YES;
dispatch_semaphore_signal(sema);
}];
});
while (!_isCallback) {
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
return _isLogined;
我已經類似地閱讀了問題, 如何等待異步調度的塊完成?
但是,當它在UI線程中被調用時,會發生死鎖,因為SDK回調也在UI線程中運行了該塊。
怎么處理呢? 謝謝。
如果SDKPlatform
將其完成塊分派回主隊列,那么您阻塞主線程直到完成塊被調用的方法肯定會死鎖,對此您無能為力。 但是這種信號量方法阻塞了主線程,因此無論如何,使異步方法表現得像同步方法一樣是不明智的方法。 您實際上應該擁抱異步模式,並在自己的代碼中采用完成塊技術。
該鏈接, 我如何等待異步調度的塊完成? ,說明了如何使用信號量使異步任務同步運行。 可悲的是,該技術被誤用為令人震驚的頻率。 具體來說,在這種情況下,信號量不是您方案中的適當模式,因為信號量模式將阻塞主線程,這是我們絕對不能在應用程序中執行的操作。
作為背景,信號燈技術在另一個線程中討論的場景中很好,因為它是一個非常不同的技術問題。 它是在測試框架而不是應用程序的特殊情況下使用的,並且在以下情況下使用:(a)測試本身必須在主線程上進行; (b)為使測試框架正常運行,它必須阻塞主線程,直到異步任務完成為止。 此外,它也恰好在該測試方案中起作用,因為完成塊不會發生在主隊列上,從而避免了您遇到的死鎖問題。
這三個條件都不適合您的情況。 不建議在您的情況下使用信號量技術。
因此,讓我們退后一步,看看您的問題。 我假設您有一些類似的方法:
- (BOOL) login
{
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
__block BOOL _isLogined;
__block BOOL _isCallback = NO;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^ {
//Put your heavy code here it will not block the user interface
[[SDKPlatform defaultPlatform] SDKIsLogined:^(BOOL isLogined){
_isLogined = isLogined;
_isCallback = YES;
dispatch_semaphore_signal(sema);
}];
});
while (!_isCallback) {
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
return _isLogined;
}
即使您沒有死鎖問題,這仍然是錯誤的模式。 您可能想要的是:
- (void)loginWithCompletionHandler:(void (^)(BOOL isLoggedIn))completionHandler
{
[[SDKPlatform defaultPlatform] SDKIsLogined:^(BOOL isLoggedIn){
if (completionHandler) {
completionHandler(isLoggedIn);
}
}];
}
注意,此函數具有void
返回類型,但是isLoggedIn
狀態由完成塊返回(並且應僅在完成塊內使用,如下所示:
[self loginWithCompletionHandler:^(BOOL isLoggedIn) {
// feel free to use isLoggedIn here
}];
// don't try to use isLoggedIn here
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.