如何利用 PromiseKit 确保在继续之前已检索到查询的对象?
Posted
技术标签:
【中文标题】如何利用 PromiseKit 确保在继续之前已检索到查询的对象?【英文标题】:How to utilize PromiseKit to ensure a queried object has been retrieved before proceeding? 【发布时间】:2017-03-14 15:32:35 【问题描述】:我正在编写一个使用解析服务器(由 heroku 托管)数据库的应用程序。我有几个从数据库中提取信息的函数,但它们本质上都是异步的(因为 parse 的 .findObjectinBackground
工作方式。)这个问题是因为后来的数据库查询需要来自先前查询的信息。由于被拉取的信息是异步的,我决定实现 PromiseKit 以确保在运行第二个查询之前从第一个查询的findObjectinBackground
找到对象。
查询的一般形式如下:
let query = PFQuery(classname: "Hello")
query?.findObjectsInBackground(block: (objects, error) in
if let objectss = objects
for object in objectss //object needs to be pulled
arrayOfInterest.append(object)
//array must be appended before moving on to next query
)
我只是不知道该怎么做。这是我想实现它的方式:
import PromiseKit
override func viewDidLoad()
when(/*query object is retrieved/array is appended*/).then
//perform the next query
我根本不知道在when()
和.then
中要放什么。我尝试将查询放入它们自己的单独函数中,并在这两个(when 和 then)函数中调用它们,但我基本上被告知我不能,因为它们返回 void。另外,我不能简单地确保when()
中的第一个查询是run,因为query.findObjectinBackground
(在查询中)是异步的问题。在触发下一个对象之前,需要拉动对象,而不仅仅是运行查询。
【问题讨论】:
【参考方案1】:Do you want create your promise?
您需要编写一个返回Promise<Any>
的函数。在您的情况下,需要将整个代码封装在Promise fulfill, reject in HERE
中。例如:
func foo(className: String) -> Promise<[TypeOfArrayOfInterest]>
return Promise fulfill, reject in
let query = PFQuery(classname: className)
query?.findObjectsInBackground(block: (objects, error) in
if let error = error
reject(error) // call reject when some error happened
return
if let objectss = objects
for object in objectss
arrayOfInterest.append(object)
fulfill(arrayOfInterest) // call fulfill with some value
)
然后,你在firstly
中调用这个函数:
firstly
foo(className: "Hello")
.then myArrayOfInterest -> Void in
// do thing with myArrayOfInterest
.catch error in
// some error happened, and the reject was called!
另外,我在我的博客中写了一篇关于 PromiseKit 和架构等内容的文章。可能会有所帮助:http://macalogs.com.br/ios/rails/ifce/2017/01/01/experiencias-eventbee.html
编辑
更完整的例子:
func foo() -> Promise<Int>
...
func bar(someText: String) -> Promise<String>
...
func baz() -> Promise<Void>
...
func runPromises()
firstly
foo()
.then value -> Promise<Any> in
if value == 0
return bar(someText: "no")
else
return bar(someText: "yes")
.then _ /* I don't want a String! */ -> Promise<Void> in
baz()
.catch error in
// some error happened, and the reject was called!
或者如果你不想要catch
:
_ = firstly
foo()
.then _ in
// do some thing
Swift 有更好的类型推断,但是,当使用 PromiseKit 时,我建议总是在 then
闭包中写一个类型,以避免错误。
【讨论】:
我明白你的回答,但我需要在.then
语句中使用foo()
的结果吗?我只想确保 foo()
运行(并附加数组),然后使用 .then
我只想运行另一个查询。这可行吗?
只是为了说明我之前评论的意思,我真正想要的是:firstly foo() .then _ in otherQuery() .then _ in thirdQuery() . catch error in print(error)
@AlekPiasecki 是的,你可以做到,但是,也许你需要明确地写一个返回类型,在这种情况下,then _ -> Promise<Any> in ...
。我编辑了我的答案,以举例说明。以上是关于如何利用 PromiseKit 确保在继续之前已检索到查询的对象?的主要内容,如果未能解决你的问题,请参考以下文章
在 Swift 中,如何在继续编写代码之前安全地确保从 Google 检索数据(日期和时间)?