Swift 使用承诺的代码不';根本不执行
我花了一天的大部分时间在这件事上把头撞在墙上,我想我终于明白了。这是一个我希望在今天早上我开始寻找时就存在的问题Swift 使用承诺的代码不';根本不执行,swift,promise,promisekit,Swift,Promise,Promisekit,我花了一天的大部分时间在这件事上把头撞在墙上,我想我终于明白了。这是一个我希望在今天早上我开始寻找时就存在的问题 背景,我有几年的C++和Python的经验,最近我开始学习Swift来开发非iOS。我将在这里展示的一切在MacBook Pro上的表现似乎与在我的Ubuntu PC上的表现相同。我正在运行Swift 5.4,在命令行中使用Swift软件包管理器进行编译和运行 我已经阅读了几篇关于在Swift中使用承诺的文章,但这些文章都不完整。他们展示的例子让人觉得你可以先调用,,将几个链接在一起
背景,我有几年的C++和Python的经验,最近我开始学习Swift来开发非iOS。我将在这里展示的一切在MacBook Pro上的表现似乎与在我的Ubuntu PC上的表现相同。我正在运行Swift 5.4,在命令行中使用Swift软件包管理器进行编译和运行
我已经阅读了几篇关于在Swift中使用承诺的文章,但这些文章都不完整。他们展示的例子让人觉得你可以先调用,,将几个链接在一起。然后调用,然后用.done
和.catch
,一切都会正常工作。当我尝试这个方法时,我通常会遇到一大堆错误,但有时我很幸运地编译了它,结果却发现在运行它时什么都没有发生
下面是一个示例main.swift
文件,它说明了我的困惑
import PromiseKit
firstly {
Promise<String> { seal in
print("Executing closure")
seal.fulfill("Hello World!")
}
}.done { str in
print(str)
}
我希望它打印Stack Overflow主页的HTML内容,但它不打印任何内容
看起来我已经准备好了所有的设置,但是承诺没有兑现。如何让它们真正执行?这里的问题似乎是所有的在线文章都关注iOS开发,而不是真正解决桌面/服务器可执行文件中的承诺。简单脚本旨在终止,而移动应用程序则设计为无限期运行
如果您深入研究表
代码,您会发现。然后
、。完成
、。捕获
,等等都有一个调度队列
的参数,深入研究后,该参数默认为调度队列.main
。由于这些示例中的顶级代码使用的是主线程,因此主DispatchQueue
从未获得执行分配给它的工作的机会。通过在最后调用dispatchMain()
将主线程交给调度系统,这两个示例都可以很容易地执行承诺链
但是,dispatchMain()
永远不会返回,因此对于打算运行到完成的可执行文件来说,这不是一个好的选择。更好的解决方案是指定一个备用队列来执行这些承诺。对于单个任务,我们可以在块中使用信号量。最后,
块发出所有工作都已完成的信号。对于多个任务,我怀疑您需要使用DispatchGroup
以下是第一个示例的更新版本:
import Foundation
import PromiseKit
let queue = DispatchQueue.global()
let semaphore = DispatchSemaphore(value: 0)
firstly {
Promise<String> { seal in
print("Executing closure")
seal.fulfill("Hello World!")
}
}.done(on: queue) { str in
print(str)
}.catch(on: queue) { error in
print("Error: \(error)")
}.finally(on: queue) {
semaphore.signal()
}
semaphore.wait()
<代码>导入基础
进口承诺书
let queue=DispatchQueue.global()
让信号量=分派信号量(值:0)
首先{
承诺{盖章
打印(“执行关闭”)
seal.fulfill(“你好,世界!”)
}
}.done(on:queue){str in
打印(str)
}.catch(在:队列上){中出错
打印(“错误:\(错误)”)
}.最后(关于:队列){
信号量
}
信号量。等待()
这是第二个的工作版本:
import Foundation
import PromiseKit
let queue = DispatchQueue.global()
let semaphore = DispatchSemaphore(value: 0)
let url = URL(string: "https://stackoverflow.com/")!
enum SampleError: Error {
case noResponse
case badCode(Int)
case couldNotDecode
}
firstly {
Promise<Data> { seal in
URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
return seal.reject(error)
}
guard let data = data, let response = response as? HTTPURLResponse else {
return seal.reject(SampleError.noResponse)
}
guard (200..<300).contains(response.statusCode) else {
return seal.reject(SampleError.badCode(response.statusCode))
}
seal.fulfill(data)
}.resume()
}
}.then(on: queue) { data -> Promise<String> in
Promise<String> { seal in
if let str = String(data: data, encoding: .utf8) {
seal.fulfill(str)
} else {
seal.reject(SampleError.couldNotDecode)
}
}
}.done(on: queue) { str in
print(str)
}.catch(on: queue) { error in
print("Error: \(error)")
}.finally (on: queue) {
semaphore.signal()
}
semaphore.wait()
<代码>导入基础
进口承诺书
let queue=DispatchQueue.global()
让信号量=分派信号量(值:0)
让url=url(字符串:https://stackoverflow.com/")!
枚举采样错误:错误{
案例无应答
案例代码(内部)
案例无法解码
}
首先{
承诺{盖章
URLSession.shared.dataTask(with:url){data,response,中的错误
如果let error=error{
退回封条。拒绝(错误)
}
保护let data=data,let response=response as?httpurresponse else{
返回密封。拒绝(样本错误。无响应)
}
守卫(200..承诺
承诺{盖章
如果let str=String(数据:数据,编码:.utf8){
密封件(str)
}否则{
密封。拒绝(样本错误。无法解码)
}
}
}.done(on:queue){str in
打印(str)
}.catch(在:队列上){中出错
打印(“错误:\(错误)”)
}.最后(关于:队列){
信号量
}
信号量。等待()
有趣的是,first
块似乎在主线程上同步执行。我突然想到,如果要运行大量任务,最好在first
处理程序中尽可能少地执行工作,并释放主线程,以便它可以更快地启动其他线程上的任务。似乎这里的问题在于,所有在线文章都集中在iOS开发上,并没有真正解决桌面/服务器可执行文件中的承诺。简单的脚本旨在终止,而移动应用程序设计为无限期运行
如果深入研究表
代码,您会发现.then
、.done
、.catch
,等等都有一个调度队列
的参数,深入研究后,默认为调度队列.main
。因为这些示例中的顶级代码使用的是主线程mainode>DispatchQueue
从来没有机会执行分配给它的工作。这两个示例都可以通过在最后调用dispatchMain()
将主线程交给调度系统来轻松执行承诺链
但是,dispatchMain()
永远不会返回,因此对于打算运行到完成的可执行文件来说,这不是一个好的选择。更好的解决方案是指定一个备用队列来执行每个承诺。对于单个任务,我们可以在块中使用一个信号量。最后
块来表示所有工作都已完成。对于多个任务,我怀疑您会这样做需要使用调度组
以下是第一个示例的更新版本:
import Foundation
import PromiseKit
let queue = DispatchQueue.global()
let semaphore = DispatchSemaphore(value: 0)
firstly {
Promise<String> { seal in
print("Executing closure")
seal.fulfill("Hello World!")
}
}.done(on: queue) { str in
print(str)
}.catch(on: queue) { error in
print("Error: \(error)")
}.finally(on: queue) {
semaphore.signal()
}
semaphore.wait()
<代码>导入基础
进口承诺书
让