如何利用 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 _ -&gt; Promise&lt;Any&gt; in ... 。我编辑了我的答案,以举例说明。

以上是关于如何利用 PromiseKit 确保在继续之前已检索到查询的对象?的主要内容,如果未能解决你的问题,请参考以下文章

在 openMP 中,如何确保线程在继续之前同步?

如何确保 .then() 中的功能在继续之前完成?

在 Dart 中,如何确保流更新在继续之前完成?

在 Swift 中,如何在继续编写代码之前安全地确保从 Google 检索数据(日期和时间)?

如何使用 Combine + Swift 复制 PromiseKit 风格的链式异步流

While Loop 在 Promisekit 完成运行并在 Swift 中返回正确的值之前递增并重新运行