freshOS / Then

:clapper: Tame async code with battle-tested promises
MIT License
993 stars 77 forks source link

whenAll not fulfilled nor rejected #39

Closed cfanfs closed 6 years ago

cfanfs commented 6 years ago

Hello, I have an issue with whenAll

I have a piece of code like this:

func download(from url: URL) -> Promise<Void> { ... }
...
let promises = downloadURLs.map(download(from:))
Promises.whenAll
  .then { ... }
  .onError { _ in ... }

This code randomly fails. I can find out that each of download promises are fulfilled but neither then nor onError are called.

Then I wrote a test:

    private let concurrentQueue = DispatchQueue(
        label: "then.whenAll.test.concurrent",
        qos: .userInitiated,
        attributes: .concurrent)
    func testWhenAllAllAsynchronous() {
        let values = (1...10).map { $0 }
        let promises: [Promise<Int>] = values.map { value in
            return Promise { fulfill, _ in
                self.concurrentQueue.async {
                    fulfill(value)
                }
            }
        }
        let block = expectation(description: "Block called")
        Promises.whenAll(promises).then { array in
            XCTAssertEqual(Set(array), Set(values))
            block.fulfill()
        }
        waitForExpectations(timeout: 3, handler: nil)
    }

and it fails.

Looks like the temporary variable var ts = [T]() has a thread race issue, and registerFinally is not an atomic operation.

Thank you.

s4cha commented 6 years ago

https://github.com/freshOS/then/releases/tag/4.1.0 :)

Thanks again, you rock!