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

Returning promise that uses another promise with PromiseKit

这是这个问题的代码示例:

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 函数。

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

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

我觉得这有点丑陋,并且违背了 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: I'm not looking for some overly complex, over-engineered solution to flattening that out. I'm just trying to follow some sort of best practice, being nested isn't the problem, I just want to be doing things "properly"

函数func filterData(_ data: [Foo]) -> Promise<[Foo]>期望return承诺。 在你的情况下表达式

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

returns 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([=11=].id) })
        }
    }
}

更新: 要了解问题所在,您可以显式声明 return 参数的类型。然后你会看到什么类型需要 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([=12=].id) })
        }
    }
}