返回使用另一个 PromiseKit 承诺的承诺

Posted

技术标签:

【中文标题】返回使用另一个 PromiseKit 承诺的承诺【英文标题】:Returning promise that uses another promise with PromiseKit 【发布时间】:2017-09-23 10:52:17 【问题描述】:

这是这个问题所涉及的代码示例:

func executeTask() 
    fetchApiData().then  foos in
        return filterData(foos) 
    .then  foos in
        return saveData(foos)
    .catch 
        /** handle error **/
        


func fetchApiData() -> Promise<[Foo]> 
    return Promise<[Foo]>  fulfil, reject in
        /* Do a network request, and run through object mapper */
        fulfil( myFooCollection )
    


func filterData(_ data: [Foo]) -> Promise<[Foo]> 

    return Promise<[Foo]>  fulfil, _ in

        _ = getIdsToFilter().then  ids -> Void in

            let filteredData = data.filter  foo in
                return ids.contains(foo.id)
            

            fulfil(filteredData)

        

    



func getIdsToFilter() -> Promise<[Int]> 
    return Promise<[Int]>  fulfil, _ in 
        /* Do some task here */
        fulfil([10,20,30,40])
    


func saveData(_ data: [Foo]) -> Promise<[Foo]> 
    return Promise<[Foo]>  fulfil, reject in 
            /* Do some save task here */
            fulfil(data)
        

我特别查询的函数是filterData

这是一个非常简单的 Promise 链,获取一些数据,过滤它,然后保存它。但是,过滤过程需要另一个 Promise 的响应才能完成。

如您所见,我已将其实现为一种包装器。我返回了我需要的承诺,但在做这件事之前,该承诺会从其自身内部调用另一个承诺。

我觉得这有点难看,违背了 Promises 的整体构图理念。我认为应该有一种方法可以代替:

func filterData(_ data: [Foo]) -> Promise<[Foo]> 

    return getIdsToFilter().then  ids in
        return data.filter  foo in
            return ids.contains(foo.id)
        
    


但是,这当然不像 xcode 所说的那样工作:

Cannot convert return expression of type '[Foo]' to return type 'Promise<[Foo]>' (aka 'Promise<Array<Foo>>')

那么...有没有办法使该功能变平?或者也许我正在做的事情是正确的,应该是这样的?

P.S:我不是在寻找一些过于复杂、过度设计的解决方案 把它弄平。我只是想遵循某种最好的 练习,嵌套不是问题,我只想做 事情“正确”

【问题讨论】:

【参考方案1】:

函数func filterData(_ data: [Foo]) -&gt; Promise&lt;[Foo]&gt; 期望返回承诺。 在你的情况下表达

data.filter  foo in
        return ids.contains(foo.id)

返回ArrayFoo 对象。您必须将 [Foo] 包装到 Promise 对象。请参阅下面的示例

func filterData(_ data: [Foo]) -> Promise<[Foo]> 
    return Promise  _ in
        return getIdsToFilter().then  ids in
            return Promise(value: data.filter  return ids.contains($0.id) )
        
    

更新: 要了解问题所在,您可以显式声明返回参数的类型。然后你会看到什么类型需要 swift 编译器以及你需要什么类型。这种策略可以帮助我理解编译器错误

func filterData(_ data: [Foo]) -> Promise<[Foo]> 
    return Promise  _ in
        return getIdsToFilter().then  ids -> Promise<[Foo]> in
            return Promise(value: data.filter  return ids.contains($0.id) )
        
    

【讨论】:

以上是关于返回使用另一个 PromiseKit 承诺的承诺的主要内容,如果未能解决你的问题,请参考以下文章

如果一个已经在运行的 PromiseKit 承诺返回一个未决的承诺的最佳 Swift 模式是啥?

iOS(ObjC)PromiseKit - 在承诺中返回承诺

PromiseKit 分支承诺

PromiseKit 2.0:链接承诺不传递参数

PromiseKit - 带有重新加载第一个承诺的可选承诺

如何使用 PromiseKit 重构快速回调以承诺