3

I'm trying to write a function that returns a promise:

func sample() -> Promise<AnyObject> {
    return Promise(1)
    .then { _ -> Void in
        debugPrint("foo")
    }.then { _ -> Void in
        debugPrint("foo")
    }
}

I get an error on the last then statement:

Declared closure result 'Void' (aka '()') is incompatible with contextual type 'AnyPromise'

I was under the impression that 'then' should implicitly returned a promise regardless; Is my thinking wrong? Should I just return a promise explicitly like so?:

func sample() -> Promise<AnyObject> {
    return Promise(1)
    .then { _ -> Void in
        debugPrint("foo")
    }.then { _ -> Promise<AnyObject> in
        debugPrint("foo")
        return Promise(1)
    }
}

Thanks

rmaddy
  • 314,917
  • 42
  • 532
  • 579
rclark
  • 301
  • 3
  • 13

2 Answers2

3

The promise returned by then(_:) matches the return value of the closure.

func sample() -> Promise<AnyObject> {
    return Promise(1)
    .then { _ -> Void in
        debugPrint("foo")
    }.then { _ -> Void in
        debugPrint("foo")
    }
}

Let me rework your method.

func sample() -> Promise<AnyObject> {
    let p1: Promise<AnyObject> = Promise(1)
    let p2: Promise<Void> = p1.then { _ -> Void in
        debugPrint("foo")
    }
    let p3: Promise<Void> = p2.then { _ -> Void in
        debugPrint("foo")
    }
    return p3
}

You can now see the expected return type of Promise<AnyObject> doesn't match actual return type of Promise<Void>.

If you want to have a method return Promise<AnyObject>, then the last promise in the promise chain must return AnyObject.

func sample() -> Promise<AnyObject> {
    return firstly { _ -> Void in
        debugPrint("foo")
    }.then { _ -> Void in
        debugPrint("foo")
    }.then { _ -> AnyObject in
        1
    }
}
Jeffery Thomas
  • 42,202
  • 8
  • 92
  • 117
  • Thanks for the excellent explanation. Its hard to understand this from reading the source & documentation. Within the block after 'firstly' I get a weird error `Ambiguous reference to member 'debugPrint(_:separator:terminator:)` on the line `debugPrint("foo")`. However I replaced that to the following: `return Promise { fulfill, reject in var fish = 1 }.then { _ -> Void in debugPrint("foo") }.then { _ -> AnyObject in 1 }` And it works fine @JefferyThomas – rclark May 15 '16 at 03:11
2

A then call returns whatever you specify in it's call, Void in your first example.

For your second attempt there, you're closer, but you're returning an unrelated Promise, which you've had to fulfill with 1 a second time.

Try this code instead:

func sample() -> Promise<AnyObject> {
    return Promise<AnyObject> { fulfill, reject in
        return Promise<AnyObject>(1)
        .then { _ -> Void in
            debugPrint("foo")
        }.then { _ -> Void in
            debugPrint("foo")
        }
    }
}

This embeds the second Promise in the first, so now your then's will run in order as well as any others you add to the promise returned by the function when it's called wherever else in your code.

Dave Wood
  • 13,143
  • 2
  • 59
  • 67
  • Thanks @DaveWood; I'm still getting the same error though with your example. I even removed the first 'then'. Here's what I have now: `func sample() -> Promise { return Promise { fulfill, reject in return Promise(1) }.then { _ -> Void in debugPrint("foo") } }` Any ideas? – rclark May 15 '16 at 02:57
  • You've changed the code again so that your `then` is on the outside promise instead of the inside promise. – Dave Wood May 15 '16 at 03:12
  • Do you know why 'fulfill' doesn't have to be called in this case? @DaveWood – rclark May 15 '16 at 04:12
  • Actually, unless I fulfill the outer promise I get this error in my log: `Promise deallocated! This is usually a bug` @DaveWood – rclark May 15 '16 at 04:30
  • Actually, I'd vote for @Jeffery-Thomas's answer as being the correct one rather than mine. His produces cleaner code without having to use an internal promise or using fulfill/reject. His explanation that the return value of the last `then` must match the type of promise returned from the method is clear. – Dave Wood May 15 '16 at 04:32