如何使用Promise Kit调用递归函数?

问题描述

我被困在某个地方,以在promise中再次调用同一函数,并且由于调用了多次,所以它重新分配了promise。实际上,在我的情况下,我有带有多个页面请求的API,我想用promise来调用它。我的实现如下。

func fetchContacts() -> Promise<FPGetContactResponse?> {
            
        return Promise { seal in

            let contactrequest = FPGetContactRequest()
            contactrequest.pageNo = getAPICurrentPageNo(Api.API_CONTACTS) + 1
            contactrequest.pageSize = SMALL_PAGE_SIZE
            
               contactrequest.doGetContacts(parameter: [:],response: { (response) in
                print("Contacts Count : \(response.Contacts?.count ?? 0)")

                if(response.Contacts?.count ?? 0 != 0){
                    _ = self.fetchContacts()

                }else{
                    seal.fulfill(response)
                }
               })
               { (error) in
                   print(error.localizedDescription)
                seal.reject(error)

            }
        }
    }

在上面的函数中,我检查联系人计数!= 0,然后需要再次调用同一函数。但是不幸的是,这是释放承诺。

我将诺言序列称为如下。

func startSyncData(handler:@escaping SyncAPIHandler){
        firstly {
            self.fetchContacts().ensure {
                handler(false,0.5,nil)
            }
        }.then { data in
            self.fetchInteractions().ensure {
                handler(false,0.7,nil)
            }
        }.then { data in
            self.fetchAddresses().ensure {
                handler(false,0.8,nil)
            }
        }.then { data in
            self.fetchLookupQuery().ensure {
            }

        }
        .done { contacts -> Void in
            //Do something with the JSON info
            print("Contacts Done")
            handler(true,nil)
        }
        .catch(policy: .allErrors) { error in
            print(error.localizedDescription)

        }

    }

请提供给我正确的方法,以在promise中再次调用同一函数

解决方法

代替使用递归,您应该在promise中返回一个响应,并在下一个.then中进行检查,并在需要时再次调用fetchContacts

fetchContacts()
.then { response -> Promise<FPGetContactResponse> in
    if (response.Contacts?.count ?? 0 != 0) {
        return fetchContacts() // Make the second call
    }
    return .value(response) // Return fullfilled promise
}
.then {
    ...
}

您还可以使用下一种方法-https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#retry--polling

为您的案件制作特殊的包装纸 ,

我用以下解决方案实现了事情。

func syncContacts() -> Promise<FPGetContactResponse?> {
      return fetchContacts().then{ seal -> Promise<FPGetContactResponse?> in
        if(seal?.Contacts?.count ?? 0 != 0){
            return self.syncContacts()
        }else{
            return Promise.value(seal)
        }
      }
    }

现在只需按如下所示的promise顺序调用syncContacts()方法即可。

 func startSyncData(handler:@escaping SyncAPIHandler){
        firstly {
            self.syncContacts().ensure {
                handler(false,0.5,nil)
            }
        }.then { data in
            self.syncInterections().ensure {
                handler(false,0.7,nil)
            }
        }.then { data in
            self.syncAddresses().ensure {
                handler(false,0.8,nil)
            }
        }.then { data in
            self.syncLookupQuery().ensure {
            }

        }
        .done { contacts -> Void in
            //Do something with the JSON info
            print("Contacts Done")
            handler(true,nil)
        }
        .catch(policy: .allErrors) { error in
            print(error.localizedDescription)

        }

    }