如何在Swift中创建基于异步/等待信号量像在JavaScript中使用Promise一样?

3z6pesqy  于 2023-06-28  发布在  Swift
关注(0)|答案(2)|浏览(129)

下面是一个简单的例子:

let unlockResolve = () => {}
async function semaphore() {
     await new Promise((resolve) => {
           unlockResolve = resolve
     })
}

async function stopAtTheRedLight() {
     await semaphore()
}

function unlocksSemaphore() {
     unlockResolve()
     unlockResolve  = () => {}
}

await stopAtTheRedLight()

// Somewhere else:
// [...]
unlocksSempahore()

基于async/await的Swift代码是什么?

p8h8hvxi

p8h8hvxi1#

关于你自己的回答:不需要闭包来恢复Continuation,只需将其保存在私有属性中即可。
我 * 删除了 * 术语semaphore的误导性出现,并将asyncAfter替换为Swift Concurrency的等价物。

actor Example {
    private var continuation : CheckedContinuation<Void,Never>?
    
    func waitOnGreen() async {
        await withCheckedContinuation { self.continuation = $0 }
    }
    
    func stopAtTheRedLight() async {
        await waitOnGreen()
    }
    
    func turnGreenAction() {
        print("Clear the traffic")
        continuation?.resume()
        continuation = nil
    }
    
    func run() async {
        print("Waiting at red light")
        await stopAtTheRedLight()
        print("Got a green and we're running again.")
    }
}

let intersection = Example()
Task {
    try? await Task.sleep(for: .seconds(2))
    await intersection.turnGreenAction()
}

await intersection.run()
vd2z7a6w

vd2z7a6w2#

**更新:**一夜之间开发出了一个锁定库,标记文档是TODO,即将推出。
https://github.com/oxygen/AsyncAwaitLock-Swift

//////////////

import Foundation
import Dispatch
import PlaygroundSupport

@MainActor
class Example {
    private var continuation: CheckedContinuation<Void, Never>? = nil {
        didSet {
            assert(oldValue == nil || continuation == nil)
        }
    }
    
    // From Apple’s docs: The checked continuation offers detection of mis-use, 
     // and dropping the last reference to it, 
     // without having resumed it will trigger a warning. 
     // Resuming a continuation twice is also diagnosed and will cause a crash.
    deinit {
        continuation?.resume()
    }
    
    func waitOnSemaphore() async {
        await withCheckedContinuation { [self] continuation in
            assert(Thread.isMainThread)
            
            self.continuation = continuation
        }
    }
    
    func stopAtTheRedLight() async {
        await waitOnSemaphore()
    }
    
    func unlockSemaphoreAction() {
        print("Unlock sempahore.")
        
        let continuation = self.continuation
        self.continuation = nil
        
        continuation?.resume()
    }
    
    func run() async {
        print("Waiting at red light")
        await stopAtTheRedLight()
        print("Got a green and we're running again.")
    }
    
}

let intersection = Example()
Task {
    try! await Task.sleep(nanoseconds: 2_000_000_000)
        
    await intersection.unlockSemaphoreAction()        
}
await intersection.run()

PlaygroundPage.current.needsIndefiniteExecution = true

// Output:
// 
// Waiting at red light
// 
// Unlock sempahore.
// Got a green and we're running again.

相关问题