Dominic
Dominic

Reputation: 95

While Loop increments and re-runs before Promisekit can finish running and return the proper value in Swift

I'm trying to use a while loop with Promisekit with Alamofire to chain four GET requests, return a value, and rerun the four requests with a new parameter. This is the current code that I'm using:

        var index = 0
        var count = classDictionary["class"]!.count-1

        while index <= count {

        firstly {
            parseBooksXML(index)
            }.then { abrevCode in
                self.parseBooksXML2(index, key: abrevCode)
            }.then { courseNumber in
                self.parseBooksXML3(index, key: courseNumber)
            }.then { instructorCode in
                self.parseBooksXML4(instructorCode)
            }
            index += 1
        }

Each of the first three functions returns a promised string value which is then passed onto the next function until the fourth and final function calls another function to parse the downloaded HTML using Kanna.

Ideally I would like all four functions to be called and completed after which the index will increment and run the loop again using the new index number. As a note, the index in passed onto the functions as a way to identify which index in an array a value should be compared to.

For clarity, I have included the code for the parseBooksXML functions below:

func parseBooksXML(index: Int) -> Promise<String> {
    return Promise {fulfill, reject in

    let headers = [
        "Referer": "URL"
    ]


    Alamofire.request(.GET, "URL", headers: headers)
        .responseData { response in

            switch response.result {
            case .Success:
                let xml = SWXMLHash.parse(response.data!)

                do {

                    let range = self.classDictionary["class"]![index].rangeOfString("[a-zA-Z]{2,4}", options: .RegularExpressionSearch)
                    let result = self.classDictionary["class"]![index].substringWithRange(range!)

                    try self.abrevCode = (xml["departments"]["department"].withAttr("abrev", result).element!.attribute(by: "id")!.text)

                }
                catch {
                    print("Error: \(error)")

                }
                fulfill(self.abrevCode)

            case .Failure(let error):
                print(error)
            }
        }
    }
}

func parseBooksXML2(index: Int, key: String) -> Promise<String> {
    return Promise {fulfill, reject in

        let headers = [
        "Referer": "URL"
    ]


    Alamofire.request(.GET, "URL", headers: headers)
        .responseData { response in

            switch response.result {
            case .Success:
                let xml = SWXMLHash.parse(response.data!)
                 do {

                    let range = self.classDictionary["class"]![index].rangeOfString("\\d\\d\\d", options: .RegularExpressionSearch)
                    let result = self.classDictionary["class"]![index].substringWithRange(range!)

                    try self.courseNumber = (xml["courses"]["course"].withAttr("name", result).element?.attribute(by: "id")?.text)!

                 }
                 catch {
                    print("Error: \(error)")

                }
                fulfill(self.courseNumber)

            case .Failure(let error):
                print(error)
            }

        }
    }
}

func parseBooksXML3(index: Int, key: String) -> Promise<String> {
    return Promise {fulfill, reject in

        let headers = [
        "Referer": "URL"
    ]

    Alamofire.request(.GET, "URL", headers: headers)
        .responseData { response in

            switch response.result {
            case .Success:
                let xml = SWXMLHash.parse(response.data!)
                do {

                    let range = self.classDictionary["class"]![index].rangeOfString("[a-zA-Z]{1,3}?\\d?\\d?\\d?$", options: .RegularExpressionSearch)
                    let result = self.classDictionary["class"]![index].substringWithRange(range!)

                    try self.instructorCode = (xml["sections"]["section"].withAttr("instructor", self.classTeacher[index]).element?.attribute(by: "id")?.text)!
                }
                catch {
                    print("Error: \(error)")


                }
                fulfill(self.instructorCode)

            case .Failure(let error):
                print(error)
            }

        }
    }
}

func parseBooksXML4(key: String) -> Void {

        let headers = [
        "Referer": "URL"
    ]

    Alamofire.request(.GET, "URL", headers: headers)
        .responseData { response in

            switch response.result {
            case .Success:
                self.parseISBN(String(data: response.data!, encoding: NSUTF8StringEncoding)!)

            case .Failure(let error):
                print(error)
            }

        }
    }

Any help would be appreciated!

Upvotes: 0

Views: 567

Answers (2)

mxcl
mxcl

Reputation: 26893

You need to use when:

let count = classDictionary["class"]!.count-1

let promises = (0..<count).map { index -> Promise<ReplaceMe> in
    return firstly {
        parseBooksXML(index)
    }.then { abrevCode in
        self.parseBooksXML2(index, key: abrevCode)
    }.then { courseNumber in
        self.parseBooksXML3(index, key: courseNumber)
    }.then { instructorCode in
        self.parseBooksXML4(instructorCode)
    }
}

when(fulfilled: promises).then {
    //…
}

Upvotes: 2

user811972
user811972

Reputation: 66

Since parseBooksXML4 call is async, you should wrap parseBooksXML4() call to return promise and wait for that to finish before increment index.

    firstly {
        parseBooksXML(index)
        }.then { abrevCode in
            self.parseBooksXML2(index, key: abrevCode)
        }.then { courseNumber in
            self.parseBooksXML3(index, key: courseNumber)
        }.then { instructorCode in
            self.parseBooksXML4(instructorCode)
        }.then { _ in
            index += 1
        }
    }

Upvotes: 0

Related Questions