嵌套的Alamofire请求和异步调度队列

问题描述 投票:0回答:2

我正在尝试实现嵌套的Alamofire请求:-第一个请求调用代码-第二个请求使用第一个请求中获得的代码调用结果

此外,我猜想DispatchQueue对象有问题,我当时在考虑对第二个请求使用DispatchQueue.main.async,但是这里不接受。

在下面的行中,第二个请求返回的结果为零,因为它没有包含在第一个请求中找到的代码。

    func fetch(jan: String) {

 AF.request("https://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemSearch?appid=\(appId)&jan=\(jan)&hits=50").responseDecodable(of: Welcome.self , queue: DispatchQueue.main) { response in 
    let boncode1 = String("\(response.value?.resultSet.the0.result.the0?.code)")     
    print(boncode1)

AF.request("https://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemLookup?appid=\(self.appId)&itemcode=\(boncode1)").responseDecodable(of: troisViewController.Welcome.self , queue: DispatchQueue.main) { response in

            print("\(response.value?.resultSet.the0.result.the0?.name ?? "is nil" )")

        }
    }
}

我希望有人已经处理过类似的问题,

提前谢谢您

swift api alamofire grand-central-dispatch dispatch-async
2个回答
0
投票

Alamofire不提供自己的异步原语。相反,您可以将Alamofire的请求与现有的原语组合在一起,也可以提供自己的原语。这里最简单的解决方案是嵌套调用:

AF.request(...).responseDecodable(of: ...) { outer in
    // Handle outer response.
    AF.request(...).responseDecodable(of: ...) { inner in
        // Handle inner response.
    }
}

此外,不需要将DispatchQueue.main传递给Alamofire,因为这是您始终要调用响应处理程序的默认队列。


0
投票

只要您需要两次服务调用,嵌套函数就可以满足您的需求。但是,假设您需要处理5个甚至更多服务呼叫的结果,那肯定是Pyramid of Doom噩梦。

为了避免它,我建议您看一下DispatchGroup API并学习如何使用它。

组允许您聚合一组任务并同步组上的行为。您将多个工作项附加到一个组,并安排它们在同一队列或不同队列上异步执行。当所有工作项完成执行时,组将执行其完成处理程序。您也可以同步等待组中的所有任务完成执行。

因此您可以像这样实现您的功能:

func fetch(jan: String) {

    // Local variable
    var boncode1: String = ""

    // Create group
    let dispatchGroup = DispatchGroup()

    // Fetch data from the first service

    let url_1 = "https://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemSearch?appid=\(appId)&jan=\(jan)&hits=50"

    // Indicate that the first block of work (first service call) has entered the group.
    dispatchGroup.enter()

    AF.request(url_1).responseDecodable(of: Welcome.self) { response in
        // Store data in local variable
        boncode1 = String("\(response.value?.resultSet.the0.result.the0?.code)")

        // Indicate that the first block in the group finished executing.
        dispatchGroup.leave()
    }

    // Fetch data from the second service

    let url_2 = "https://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemLookup?appid=\(self.appId)&itemcode=\(boncode1)"

    //Indicate that the second block of work (second service call) has entered the group.
    dispatchGroup.enter()

    AF.request(url_2).responseDecodable(of: troisViewController.Welcome.self) { response in
        // handle response from the second service if you need it

        // Indicate that the second block in the group finished executing.
        dispatchGroup.leave()
    }

    // This function schedules a notification block to be submitted to the specified queue 
    // when all blocks associated with the dispatch group have completed.
    dispatchGroup.notify(queue: .main) {
        // process results of 2 service calls
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.