如何利用 PromiseKit 确保在继续之前检索到查询的对象?

How to utilize PromiseKit to ensure a queried object has been retrieved before proceeding?

我正在编写一个使用解析服务器(由 heroku 托管)数据库的应用程序。我有几个从数据库中提取信息的函数,但它们本质上都是异步的(因为解析 .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{} 中放什么。我尝试将查询放入它们自己的单独函数中,并在这两个(何时和然后)函数中调用它们,但我基本上被告知我不能,因为它们 return 无效。此外,我不能简单地确保第一个查询是 when() 中的 运行,因为 query.findObjectinBackground(在查询中)是异步的是问题所在。该对象特别需要 拉取 ,而不仅仅是查询 运行,然后才能触发下一个对象。

Do you want create your promise?

您需要编写一个 return 和 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!
}

此外,我在我的博客中写了一篇 post,其中包括 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 闭包中写一个类型,以避免错误。